成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

php操作mysql防止sql注入(合集)

kviccn / 1882人閱讀

摘要:參考中如何防止注入?yún)?shù)化查詢?yōu)槭裁茨軌蚍乐棺⑷肷厦嫣峁┑馁Y料比較多,下面根據(jù)自己的理解整理出來(lái)。使用的預(yù)處理參數(shù)化查詢可以有效防止注入。我們?cè)谏厦骖A(yù)處理參數(shù)化查詢是在中進(jìn)行防注入操作的,其實(shí)也內(nèi)置了一個(gè)預(yù)處理的模擬器,叫做。

由于segmentfault在處理特殊字符時(shí)也并非完美,所以下面文章中有些符號(hào)被轉(zhuǎn)換了,請(qǐng)到本人博客下載原文txt http://www.yunxi365.cn/index....

本文將從sql注入風(fēng)險(xiǎn)說(shuō)起,并且比較addslashes、mysql_escape_string、mysql_real_escape_string、mysqli和pdo的預(yù)處理的區(qū)別。

當(dāng)一個(gè)變量從表單傳入到php,需要查詢mysql的話,需要進(jìn)行處理。
舉例:
$unsafe_variable = $_POST["user_input"];
mysqli_query("INSERT INTO table (column) VALUES ("" . $unsafe_variable . "")");
用戶可以輸入諸如 : value"); DROP TABLE table;-- ,SQL語(yǔ)句就變成這樣了:
INSERT INTO table (column) VALUES("value"); DROP TABLE table;--")
執(zhí)行的結(jié)果就是table表被刪掉了。

這是一種常見(jiàn)的sql注入方法,那么在程序中,應(yīng)該怎樣預(yù)防呢?

1.魔術(shù)引用 (推薦指數(shù)3)
addslashes()與stripslashes()是功能相反的函數(shù)。
addslashes()用于對(duì)變量中的" " 和NULL添加斜杠,用于避免傳入sql語(yǔ)句的參數(shù)格式錯(cuò)誤,同時(shí)如果有人注入子查詢,通過(guò)加可以將參數(shù)解釋為內(nèi)容,而非執(zhí)行語(yǔ)句,避免被mysql執(zhí)行。

不過(guò),addslashes()添加的只在php中使用,并不會(huì)寫(xiě)入mysql中。
那么,tripslashes()的作用是將加了的php變量去掉,由于不會(huì)寫(xiě)入mysql中,所以從mysql查詢出來(lái)的內(nèi)容不需要再tripslashes()。

在防注入方面,addslashes()可以防止掉大多數(shù)的注入,但是此函數(shù)并不會(huì)檢查變量的編碼,當(dāng)使用例如中文gbk的時(shí)候,由于長(zhǎng)度比較長(zhǎng) ,會(huì)將某些gbk編碼解釋成兩個(gè)ascii編碼,造成新的注入風(fēng)險(xiǎn)(俗稱寬字節(jié)注入)。見(jiàn)下面2。

如果從網(wǎng)頁(yè)表單、php、mysql都使用utf8編碼,則沒(méi)有這個(gè)問(wèn)題。
基于此函數(shù)的風(fēng)險(xiǎn),并不建議使用,推薦使用下面3中的方法。
https://segmentfault.com/q/10...

2. mysql_real_escape_string() (推薦指數(shù)4)
由于addslashes()不檢測(cè)字符集,所以有寬字節(jié)注入風(fēng)險(xiǎn),所以php中添加了這個(gè)函數(shù)。
這個(gè)函數(shù)本來(lái)是mysql的擴(kuò)展,但是由于存在寬字節(jié)的問(wèn)題,php基于mysql的擴(kuò)展開(kāi)發(fā)了此函數(shù)。

gbk寬字符漏洞導(dǎo)致的sql注入
https://www.91ri.org/8611.html
http://www.cnblogs.com/suihui...

mysql_real_escape_chars()是mysql_escape_chars()的替代用法。
與addslashes()相比,不僅會(huì)將" " NOL(ascii的0)轉(zhuǎn)義,還會(huì)把r n進(jìn)行轉(zhuǎn)義。同時(shí)會(huì)檢測(cè)數(shù)據(jù)編碼。
按php官方的描述,此函數(shù)可以安全的用于mysql。

此函數(shù)在使用時(shí)會(huì)使用于數(shù)據(jù)庫(kù)連接(因?yàn)橐獧z測(cè)字符集),并根據(jù)不同的字符集做不同的操作。如果當(dāng)前連接不存在,剛會(huì)使用上一次的連接。

mysql_real_escape_string()防注入詳解
此方法在php5.5后不被建議使用,在php7中廢除。
參考:https://segmentfault.com/q/10...

3.預(yù)處理查詢 (Prepared Statements) (推薦指數(shù)5)
使用prepared statements(預(yù)處理語(yǔ)句)和參數(shù)化的查詢,可以有效的防止sql注入。

為什么預(yù)處理和參數(shù)化查詢可以防止sql注入呢?
在傳統(tǒng)的寫(xiě)法中,sql查詢語(yǔ)句在程序中拼接,防注入(加斜杠)是在php中處理的,然后就發(fā)語(yǔ)句發(fā)送到mysql中,mysql其實(shí)沒(méi)有太好的辦法對(duì)傳進(jìn)來(lái)的語(yǔ)句判斷哪些是正常的,哪些是惡意的,所以直接查詢的方法都有被注入的風(fēng)險(xiǎn)。
在mysql5.1后,提供了類似于jdbc的預(yù)處理-參數(shù)化查詢。它的查詢方法是:

先預(yù)發(fā)送一個(gè)sql模板過(guò)去

再向mysql發(fā)送需要查詢的參數(shù)
就好像填空題一樣,不管參數(shù)怎么注入,mysql都能知道這是變量,不會(huì)做語(yǔ)義解析,起到防注入的效果,這是在mysql中完成的。

參考:
PHP中如何防止SQL注入
http://blog.csdn.net/sky_zhe/...

參數(shù)化查詢?yōu)槭裁茨軌蚍乐筍QL注入
http://www.cnblogs.com/LoveJe...

上面提供的資料比較多,下面根據(jù)自己的理解整理出來(lái)。

預(yù)處理分為兩種:
A.使用mysqli:prepare()實(shí)現(xiàn)
看一個(gè)完整的用法:
$mysqli = new mysqli("example.com", "user", "password", "database");
$stmt = $mysqli->prepare("SELECT id, label FROM test WHERE id = ?");
$stmt->bind_param(1, $city);
$stmt->execute();
$res = $stmt->get_result();
$row = $res->fetch_assoc();

a.寫(xiě)sql語(yǔ)句,然后用?占位符替代sql中的變量
b.替換變量
c.執(zhí)行
d.得到一個(gè)二進(jìn)制結(jié)果集,從二進(jìn)制結(jié)果中取出php結(jié)果集
e.遍歷結(jié)果集

使用預(yù)處理,一條查詢分兩步,所以很安全。也是php5.5及php7推薦方法。
參考:
http://www.cnblogs.com/liuzha...

B. 使用pdo實(shí)現(xiàn)
pdo是一個(gè)php官方推薦的數(shù)據(jù)庫(kù)抽象層,提供了很多實(shí)用的工具。

使用pdo的預(yù)處理-參數(shù)化查詢可以有效防止sql注入。
使用方法跟上面差不多,區(qū)別在于pdo提供了更多樣的方法。
使用這個(gè)pdo->$stmt對(duì)象進(jìn)行查詢后,會(huì)被結(jié)果集覆蓋,類型是一個(gè)二維數(shù)組。

我們?cè)谏厦骖A(yù)處理-參數(shù)化查詢是在mysql中進(jìn)行防注入操作的,其實(shí)pdo也內(nèi)置了一個(gè)預(yù)處理的模擬器,叫做ATTR_EMULATE_PREPARES。
默認(rèn)情況下,PDO會(huì)使用DSN中指定的字符集對(duì)輸入?yún)?shù)進(jìn)行本地轉(zhuǎn)義(PHP手冊(cè)中稱為native prepared statements),然后拼接成完整的SQL語(yǔ)句,發(fā)送給MySQL Server。這有些像我們平時(shí)程序中拼接變量到SQL再執(zhí)行查詢的形式。

這種情況下,PDO驅(qū)動(dòng)能否正確轉(zhuǎn)義輸入?yún)?shù),是攔截SQL注入的關(guān)鍵。然而PHP 5.3.6及老版本,并不支持在DSN中定義charset屬性(會(huì)忽略之),這時(shí)如果使用PDO的本地轉(zhuǎn)義,仍然可能導(dǎo)致SQL注入,

如果ATTR_EMULATE_PREPARES=true(默認(rèn)情況),預(yù)處理-參數(shù)化查詢?cè)趐do的模擬器中完成,模擬器根據(jù)字符集(dsn參數(shù))進(jìn)行處理,然后把語(yǔ)句發(fā)送給mysql。

如果ATTR_EMULATE_PREPARES=false,sql會(huì)分兩次把參數(shù)給送給mysql,mysql根據(jù)自身的字符集(set names )進(jìn)行處理,完成查詢。

但由于各版本差異,pdo在各版本中的實(shí)現(xiàn)程度也不一樣,有些版本還有bug,我們以php5.3.6做為分界線來(lái)進(jìn)行說(shuō)明:

php5.3.6以下版本
$pdo = new PDO("mysql:host=localhost;dbname=test;","root","pwd");
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
$pdo->exec("set names utf8");
$id = "0 or 1 =1 order by id desc";
$sql = "select * from article where id = ?";
$statement = $pdo->prepare($sql);
$statement->bindParam(1, $id);
$statement->execute();
如上,我們關(guān)閉了本地預(yù)處理模擬器,參數(shù)會(huì)直接分批發(fā)送給mysql,由mysql根據(jù)set name utf8字符集進(jìn)行檢測(cè),完成sql注入處理。以上代碼不會(huì)產(chǎn)生注入。

php5.3.6以上版本
$pdo = new PDO("mysql:host=localhost;dbname=test;charset=utf8","root","pwd");
$pdo->exec("set names utf8");
$id = "0 or 1 =1 order by id desc";
$sql = "select * from article where id = ?";
$statement = $pdo->prepare($sql);
$statement->bindParam(1, $id);
$statement->execute();
在php5.3.6以上版本中,默認(rèn)情況下ATTR_EMULATE_PREPARES開(kāi)啟,模擬器會(huì)根據(jù)new PDO()中的charset=utf8進(jìn)行檢測(cè),在模擬器上完成防注入操作。如果把模擬器關(guān)閉,也會(huì)像低版本一樣送交mysql進(jìn)行防注入處理。

參考:
PDO防注入原理分析以及使用PDO的注意事項(xiàng)
http://zhangxugg-163-com.itey...

PHP 5.3.6及以前版本的PDO的bindParam,bindValue潛在的安全隱患
http://zhangxugg-163-com.itey...

再論php 5.3.6以前版本中的PDO SQL注入漏洞問(wèn)題
http://my.oschina.net/zxu/blo...

segmentfault討論
https://segmentfault.com/q/10...

html輸出與防止xss注入
特殊字符輸出

比如" " < >有著特殊的意義,如果直接寫(xiě)到html中輸出,會(huì)引起dom格式的錯(cuò)亂,那么就需要用到特殊的輸出方法。

htmlspecialchars()
用于將一些特殊符號(hào)轉(zhuǎn)義成只有瀏覽器識(shí)別的轉(zhuǎn)義符。

舉個(gè)例子:
$a = " " ";

上面由于$a的值就是一個(gè)" ,當(dāng)它輸出在value=""之間時(shí),會(huì)破壞html原有的dom格式,導(dǎo)致html解析錯(cuò)誤。
下面那個(gè)"輸出在標(biāo)簽對(duì)之間時(shí)沒(méi)有問(wèn)題。
上面那個(gè)問(wèn)題怎么解決呢? 可以這樣:

php會(huì)向?yàn)g覽器輸出:

這個(gè)符號(hào)只有流量器認(rèn)識(shí),源碼中看到是這樣,但是瀏覽器輸出的就是一個(gè)"號(hào)。

xss注入
xss也就是常說(shuō)的跨域攻擊,這是一種在客戶端瀏覽器上面執(zhí)行的攻擊。
比如在表單或者url參數(shù)中,人為寫(xiě)入javascript代碼,看起來(lái)是普通的文字,但是被瀏覽器解析后變成可執(zhí)行的javascript動(dòng)作,用來(lái)做廣告或者攻擊等等。

舉例:
有人在發(fā)貼的時(shí)候?qū)懭肓薺avascript代碼,一打開(kāi)就彈窗口。

閱讀需要支付1元查看
<