最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用PDO防sql注入的原理分析

 更新時(shí)間:2018年12月03日 09:20:51   作者:leezhxing  
這篇文章主要給大家介紹了關(guān)于使用PDO防sql注入的原理的相關(guān)資料,文中還給大家介紹了使用PDO的注意事項(xiàng),通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

本文使用pdo的預(yù)處理方式可以避免sql注入。下面話不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧

在php手冊(cè)中'PDO--預(yù)處理語(yǔ)句與存儲(chǔ)過(guò)程'下的說(shuō)明:

  • 很多更成熟的數(shù)據(jù)庫(kù)都支持預(yù)處理語(yǔ)句的概念。什么是預(yù)處理語(yǔ)句?可以把它看作是想要運(yùn)行的 SQL 的一種編譯過(guò)的模板,它可以使用變量參數(shù)進(jìn)行定制。預(yù)處理語(yǔ)句可以帶來(lái)兩大好處:
  • 查詢(xún)僅需解析(或預(yù)處理)一次,但可以用相同或不同的參數(shù)執(zhí)行多次。當(dāng)查詢(xún)準(zhǔn)備好后,數(shù)據(jù)庫(kù)將分析、編譯和優(yōu)化執(zhí)行該查詢(xún)的計(jì)劃。對(duì)于復(fù)雜的查詢(xún),此過(guò)程要花費(fèi)較長(zhǎng)的時(shí)間,如果需要以不同參數(shù)多次重復(fù)相同的查詢(xún),那么該過(guò)程將大大降低應(yīng)用程序的速度。通過(guò)使用預(yù)處理語(yǔ)句,可以避免重復(fù)分析/編譯/優(yōu)化周 期。簡(jiǎn)言之,預(yù)處理語(yǔ)句占用更少的資源,因而運(yùn)行得更快。
  • 提供給預(yù)處理語(yǔ)句的參數(shù)不需要用引號(hào)括起來(lái),驅(qū)動(dòng)程序會(huì)自動(dòng)處理。如果應(yīng)用程序只使用預(yù)處理語(yǔ)句,可以確保不會(huì)發(fā)生SQL 注入。(然而,如果查詢(xún)的其他部分是由未轉(zhuǎn)義的輸入來(lái)構(gòu)建的,則仍存在 SQL 注入的風(fēng)險(xiǎn))。
  • 預(yù)處理語(yǔ)句如此有用,以至于它們唯一的特性是在驅(qū)動(dòng)程序不支持的時(shí)PDO 將模擬處理。這樣可以確保不管數(shù)據(jù)庫(kù)是否具有這樣的功能,都可以確保應(yīng)用程序可以用相同的數(shù)據(jù)訪問(wèn)模式。  

下邊分別說(shuō)明一下上述兩點(diǎn)好處:

1.首先說(shuō)說(shuō)mysql的存儲(chǔ)過(guò)程,mysql5中引入了存儲(chǔ)過(guò)程特性,存儲(chǔ)過(guò)程創(chuàng)建的時(shí)候,數(shù)據(jù)庫(kù)已經(jīng)對(duì)其進(jìn)行了一次解析和優(yōu)化。其次,存儲(chǔ)過(guò)程一旦執(zhí)行,在內(nèi)存中就會(huì)保留一份這個(gè)存儲(chǔ)過(guò)程,這樣下次再執(zhí)行同樣的存儲(chǔ)過(guò)程時(shí),可以從內(nèi)存中直接中讀取。mysql存儲(chǔ)過(guò)程的使用可以參看:http://m.fzitv.net/article/7032.htm

對(duì)于PDO,原理和其相同,只是PDO支持EMULATE_PREPARES(模擬預(yù)處理)方式,是在本地由PDO驅(qū)動(dòng)完成,同時(shí)也可以不使用本地的模擬預(yù)處理,交由mysql完成,下邊會(huì)對(duì)這兩種情況進(jìn)行說(shuō)明。

2.防止sql注入,我通過(guò)tcpdump和wireshark結(jié)合抓包來(lái)分析一下。

在虛擬機(jī)上執(zhí)行一段代碼,對(duì)遠(yuǎn)端mysql發(fā)起請(qǐng)求:

<?php

$pdo = new PDO("mysql:host=10.121.95.81;dbname=thor_cms;charset=utf8", "root","qihoo@360@qihoo");

$st = $pdo->prepare("select * from share where id =? and uid = ?");

$id = 6;
$uid = 521;

$st->bindParam(1, $id);
$st->bindParam(2, $uid);

$st->execute();
$ret = $st->fetchAll();

print_r($ret);

通過(guò)tcpdump抓包生成文件:

tcpdump -ieth0 -A -s 3000 port 3306 -w ./mysql.dump

sz mysql.dump

通過(guò)wireshark打開(kāi)文件:

可以看到整個(gè)過(guò)程:3次握手--Login Request--Request Query--Request Quit

查看Request Query包可以看到:

咦?這不也是拼接sql語(yǔ)句么?

其實(shí),這與我們平時(shí)使用mysql_real_escape_string將字符串進(jìn)行轉(zhuǎn)義,再拼接成SQL語(yǔ)句沒(méi)有差別,只是由PDO本地驅(qū)動(dòng)完成轉(zhuǎn)義的(EMULATE_PREPARES)

這種情況下還是有可能造成SQL 注入的,也就是說(shuō)在php本地調(diào)用pdo prepare中的mysql_real_escape_string來(lái)操作query,使用的是本地單字節(jié)字符集,而我們傳遞多字節(jié)編碼的變量時(shí),有可能還是會(huì)造成SQL注入漏洞(php 5.3.6以前版本的問(wèn)題之一,這也就解釋了為何在使用PDO時(shí),建議升級(jí)到php 5.3.6+,并在DSN字符串中指定charset的原因)。

針對(duì)php 5.3.6以前版本,以下代碼仍然可能造成SQL注入問(wèn)題:

$pdo->query('SET NAMES GBK'); 

$var = chr(0xbf) . chr(0x27) . " OR 1=1 /*"; 

$query = "SELECT * FROM info WHERE name = ?"; 

$stmt = $pdo->prepare($query); 

$stmt->execute(array($var));

而正確的轉(zhuǎn)義應(yīng)該是給mysql Server指定字符集,并將變量發(fā)送給MySQL Server完成根據(jù)字符轉(zhuǎn)義。

那么,如何才能禁止PHP本地轉(zhuǎn)義而交由MySQL Server轉(zhuǎn)義呢?

PDO有一項(xiàng)參數(shù),名為PDO::ATTR_EMULATE_PREPARES ,表示是否使用PHP本地模擬prepare,此項(xiàng)參數(shù)默認(rèn)true,我們改為false后再抓包看看。

先在代碼第一行后添加

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

再次用tcpdump抓包,通過(guò)wireshark我們可以看到:

php對(duì)sql語(yǔ)句發(fā)送采用了prepare--execute方式

 

這次的變量轉(zhuǎn)義處理交由mysql server來(lái)執(zhí)行。

既然變量和SQL模板是分兩次發(fā)送的,那么就不存在SQL注入的問(wèn)題了,但明顯會(huì)多一次傳輸,這在php5.3.6之后是不需要的。

使用PDO的注意事項(xiàng)

1.  php升級(jí)到5.3.6+,生產(chǎn)環(huán)境強(qiáng)烈建議升級(jí)到php 5.3.9+ php 5.4+,php 5.3.8存在致命的hash碰撞漏洞。

2. 若使用php 5.3.6+, 請(qǐng)?jiān)谠赑DO的DSN中指定charset屬性。小于5.3.6 : $dbh = new PDO($dsn,$user,$pass,array(PDO::MYSQL_ATTR_INIT_COMMAND => "set names utf8"));

3. 如果使用了PHP 5.3.6及以前版本,設(shè)置PDO::ATTR_EMULATE_PREPARES參數(shù)為false(即由MySQL server進(jìn)行變量處理),php 5.3.6以上版本已經(jīng)處理了這個(gè)問(wèn)題,無(wú)論是使用本地模擬prepare還是調(diào)用mysql server的prepare均可。

4. 如果使用了PHP 5.3.6及以前版本, 因Yii框架默認(rèn)并未設(shè)置ATTR_EMULATE_PREPARES的值,請(qǐng)?jiān)跀?shù)據(jù)庫(kù)配置文件中指定emulatePrepare的值為false。 

注:

1.為什么在DSN中指定了charset, 還需要執(zhí)行set names <charset>呢?

其實(shí)set names <charset>有兩個(gè)作用:

  告訴mysql server, 客戶(hù)端(PHP程序)提交給它的編碼是什么

      告訴mysql server, 客戶(hù)端需要的結(jié)果的編碼是什么

也就是說(shuō),如果數(shù)據(jù)表使用gbk字符集,而PHP程序使用UTF-8編碼,我們?cè)趫?zhí)行查詢(xún)前運(yùn)行set names utf8, 告訴mysql server正確編碼即可,無(wú)須在程序中編碼轉(zhuǎn)換。這樣我們以u(píng)tf-8編碼提交查詢(xún)到mysql server, 得到的結(jié)果也會(huì)是utf-8編碼。省卻了程序中的轉(zhuǎn)換編碼問(wèn)題,不要有疑問(wèn),這樣做不會(huì)產(chǎn)生亂碼。

那么在DSN中指定charset的作用是什么? 只是告訴PDO, 本地驅(qū)動(dòng)轉(zhuǎn)義時(shí)使用指定的字符集(并不是設(shè)定mysql server通信字符集),設(shè)置mysql server通信字符集,還得使用set names <charset>指令。

2.PDO::ATTR_EMULATE_PREPARES屬性設(shè)置為false引發(fā)的血案:http://my.oschina.net/u/437615/blog/369481

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • MySQL 觸發(fā)器詳解及簡(jiǎn)單實(shí)例

    MySQL 觸發(fā)器詳解及簡(jiǎn)單實(shí)例

    這篇文章主要介紹了MySQL 觸發(fā)器詳解及簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • MySQL timestamp自動(dòng)更新時(shí)間分享

    MySQL timestamp自動(dòng)更新時(shí)間分享

    在mysql中timestamp數(shù)據(jù)類(lèi)型是一個(gè)比較特殊的數(shù)據(jù)類(lèi)型,他可以自動(dòng)在你不使用程序更新情況下只要你更新了記錄timestamp會(huì)自動(dòng)更新時(shí)間
    2013-06-06
  • Mysql啟動(dòng)的方式(四種)

    Mysql啟動(dòng)的方式(四種)

    本文給大家介紹四種mysql啟動(dòng)方式,實(shí)用性非常高,感興趣的朋友參考下吧
    2016-04-04
  • mysql?sum(if())和count(if())的用法說(shuō)明

    mysql?sum(if())和count(if())的用法說(shuō)明

    這篇文章主要介紹了mysql?sum(if())和count(if())的用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 關(guān)于MySQL死鎖的產(chǎn)生原因、檢測(cè)與解決方式

    關(guān)于MySQL死鎖的產(chǎn)生原因、檢測(cè)與解決方式

    這篇文章主要介紹了關(guān)于MySQL死鎖的產(chǎn)生原因、檢測(cè)與解決方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • mysql 字符串轉(zhuǎn)數(shù)組的實(shí)現(xiàn)示例

    mysql 字符串轉(zhuǎn)數(shù)組的實(shí)現(xiàn)示例

    有時(shí)候,我們需要將一個(gè)字符串拆分成一個(gè)數(shù)組,本文主要介紹了mysql 字符串轉(zhuǎn)數(shù)組的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-01-01
  • mysql8.0.12如何重置root密碼

    mysql8.0.12如何重置root密碼

    這篇文章主要為大家詳細(xì)介紹了mysql8.0.12如何重置root密碼,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • MySQL 8.0.20 Window10免安裝版配置及Navicat管理教程圖文詳解

    MySQL 8.0.20 Window10免安裝版配置及Navicat管理教程圖文詳解

    這篇文章主要介紹了MySQL 8.0.20 Window10免安裝版配置及Navicat管理,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • MySQL中SHOW DATABASES語(yǔ)句查看或顯示數(shù)據(jù)庫(kù)

    MySQL中SHOW DATABASES語(yǔ)句查看或顯示數(shù)據(jù)庫(kù)

    在MySQL中,可使用SHOW DATABASES語(yǔ)句來(lái)查看或顯示當(dāng)前用戶(hù)權(quán)限范圍以?xún)?nèi)的數(shù)據(jù)庫(kù),下面就來(lái)介紹一下如何使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • 如何修改Mysql中g(shù)roup_concat的長(zhǎng)度限制

    如何修改Mysql中g(shù)roup_concat的長(zhǎng)度限制

    在mysql中,有個(gè)函數(shù)叫“group_concat”,平常使用可能發(fā)現(xiàn)不了問(wèn)題,在處理大數(shù)據(jù)的時(shí)候,會(huì)發(fā)現(xiàn)內(nèi)容被截取了。怎么解決這一問(wèn)題呢,下面腳本之家小編給大家?guī)?lái)了Mysql中g(shù)roup_concat的長(zhǎng)度限制問(wèn)題,感興趣的朋友一起看看吧
    2018-08-08

最新評(píng)論

乐亭县| 赞皇县| 响水县| 读书| 临桂县| 离岛区| 汝城县| 宜兴市| 茂名市| 保定市| 绵竹市| 买车| 乾安县| 武定县| 朔州市| 莱州市| 温宿县| 乐都县| 赤峰市| 柳林县| 黑山县| 济阳县| 开阳县| 南川市| 包头市| 新巴尔虎右旗| 南和县| 中超| 金塔县| 当涂县| 冷水江市| 镇坪县| 绿春县| 永昌县| 云霄县| 浙江省| 侯马市| 凤翔县| 上思县| 东台市| 东阿县|