php安全编程—sql注入攻击
php安全編程——sql注入攻擊
定義
根據(jù)相關(guān)技術(shù)原理,SQL注入可以分為平臺層注入和代碼層注入。前者由不安全的數(shù)據(jù)庫配置或數(shù)據(jù)庫平臺的漏洞所致;后者主要是由于程序員對輸入未進行細致地過濾,從而執(zhí)行了非法的數(shù)據(jù)查詢。基于此,SQL注入的產(chǎn)生原因通常表現(xiàn)在以下幾方面:
- 不當?shù)念愋吞幚?#xff1b;
- 不安全的數(shù)據(jù)庫配置;
- 不合理的查詢集處理;
- 不當?shù)腻e誤處理;
- 轉(zhuǎn)義字符處理不合適;
- 多個提交處理不當。
在某些表單中,用戶輸入的內(nèi)容直接用來構(gòu)造動態(tài)sql命令,或者作為存儲過程的輸入?yún)?shù),這些表單特別容易受到sql注入的攻擊。而許多網(wǎng)站程序在編寫時,沒有對用戶輸入的合法性進行判斷或者程序中本身的變量處理不當,使應(yīng)用程序存在安全隱患。這樣,用戶就可以提交一段數(shù)據(jù)庫查詢的代碼,根據(jù)程序返回的結(jié)果,獲得一些敏感的信息或者控制整個服務(wù)器,于是sql注入就發(fā)生了
常用技術(shù)
對數(shù)據(jù)庫類型、版本等信息進行識別是此類型攻擊的動機所在。它的目的是收集數(shù)據(jù)庫的類型、結(jié)構(gòu)等信息為其他類型的攻擊做準備,可謂是攻擊的一個預(yù)備步驟。利用應(yīng)用程序服務(wù)器返回的默認錯誤信息而取得漏洞信息。
除HTTP響應(yīng)外,能通過通道獲取數(shù)據(jù),然而,通道大都依賴與數(shù)據(jù)庫支持的功能而存在,所以這項技術(shù)不完全適用于所有的數(shù)據(jù)庫平臺。SQL注入的非主流通道主要有E-mail、DNS以及數(shù)據(jù)庫連接,基本思想為:先對SQL查詢打包,然后借助非主流通道將信息反饋至攻擊者。
不同的SQL數(shù)據(jù)庫有許多不同是特殊字符和變量,通過某些配置不安全或過濾不細致的應(yīng)用系統(tǒng)能夠取得某些有用的信息,從而對進一步攻擊提供方向。
此方式具體可分為基于內(nèi)容、基于時間、基于錯誤三種形式。一般在經(jīng)過常規(guī)訪問后加上條件語句,根據(jù)信息反饋來判定被攻擊的目標
通過某些標準存儲過程,數(shù)據(jù)庫廠商對數(shù)據(jù)庫的功能進行擴展的同時,系統(tǒng)也可與進行交互。部分存儲過程可以讓用戶自行定義。通過其他類型的攻擊收集到數(shù)據(jù)庫的類型、結(jié)構(gòu)等信息后,便能夠建構(gòu)執(zhí)行存儲過程的命令。這種攻擊類型往往能達到遠程命令執(zhí)行、特權(quán)擴張、拒絕服務(wù)的目的。
雖然對于通常的編碼都可利用某些過濾技術(shù)進行SQL注入防范,但是鑒于此種情況下也有許多方法避開過濾,一般可達到此目的的技術(shù)手段包括SQL注釋和動態(tài)查詢的使用,利用截斷,URL編碼與空字節(jié)的使用,大小寫變種的使用以及嵌套剝離后的表達式等等。借助于此些手段,輸入構(gòu)思后的查詢可以避開輸入過濾,從而攻擊者能獲得想要的查詢結(jié)果。
能夠明確數(shù)據(jù)庫模式、提取數(shù)據(jù)以及識別可注入?yún)?shù)。此種方式的攻擊通過網(wǎng)站對用戶輸入的反饋信息,對可注入?yún)?shù)、數(shù)據(jù)庫模式推斷,這種攻擊構(gòu)造的查詢執(zhí)行后獲得的答案只有真、假兩種。基于推斷的注入方式主要分為時間測定注入與盲注入兩種。前者是在注入語句里加入語句諸如“waitfor 100”,按照此查詢結(jié)果出現(xiàn)的時間對注入能否成功和數(shù)據(jù)值范圍的推導(dǎo)進行判定;后者主要是“and l=l”、“and l=2”兩種經(jīng)典注入方法。這些方式均是對一些間接關(guān)聯(lián)且能取得回應(yīng)的問題進行提問,進而通過響應(yīng)信息推斷出想要信息,然后進行攻擊
防范方法
強制字符格式(類型)
- 對于整形變量, 運用 intval函數(shù)將數(shù)據(jù)轉(zhuǎn)換成整數(shù)
- 浮點型參數(shù):運用 floatval或doubleval函數(shù)分別轉(zhuǎn)換單精度和雙精度浮點型參數(shù)
- 字符型參數(shù):運用 addslashes函數(shù)來將單引號“’”轉(zhuǎn)換成“\’”,雙引號“"”轉(zhuǎn)換成“"”,反斜杠“\”轉(zhuǎn)換成“\”,NULL字符加上反斜杠“\”如果是字符型,先判斷magic_quotes_gpc是否為On,當不為On的時候運用 addslashes轉(zhuǎn)義特殊字符
SELECT * FROM article WHERE articleid='$id'
沒有把變量放進單引號中,那我們所提交的一切,只要包含空格,那空格后的變量都會作為SQL語句執(zhí)行,給了攻擊者構(gòu)造特殊sql語句的可能。因此,我們要養(yǎng)成給SQL語句中變量加引號的習慣
使用pdo 使用 prepared statements ( 預(yù)處理語句 )和參數(shù)化的查詢。這些SQL語句被發(fā)送到數(shù)據(jù)庫服務(wù)器,它的參數(shù)全都會被單獨解析。使用這種方式,攻擊者想注入惡意的SQL是不可能的
使用PDO訪問MySQL數(shù)據(jù)庫時,真正的real prepared statements 默認情況下是不使用的。為了解決這個問題,你必須禁用 prepared statements的仿真效果。下面是使用PDO創(chuàng)建鏈接的例子:
<?php $dbh = new PDO('mysql:dbname=mydb;host=127.0.0.1;charset=utf8', 'root', 'pass'); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); ?>這可以確保SQL語句和相應(yīng)的值在傳遞到mysql服務(wù)器之前是不會被PHP解析的(禁止了所有可能的惡意SQL注入攻擊)
完整示例代碼:
<?php $dbh = new PDO("mysql:host=localhost; dbname=mydb", "root", "pass"); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //禁用prepared statements的仿真效果 $dbh->exec("set names 'utf8'"); $sql="select * from table where username = ? and password = ?"; $query = $dbh->prepare($sql); $exeres = $query->execute(array($username, $pass)); if ($exeres) { while ($row = $query->fetch(PDO::FETCH_ASSOC)) { print_r($row); } } $dbh = null; ?> 當調(diào)用 prepare() 時,查詢語句已經(jīng)發(fā)送給了數(shù)據(jù)庫服務(wù)器,此時只有占位符 ? 發(fā)送過去,沒有用戶提交的數(shù)據(jù);當調(diào)用到 execute()時,用戶提交過來的值才會傳送給數(shù)據(jù)庫,它們是分開傳送的,兩者獨立的,SQL攻擊者沒有一點機會。如下幾種情況,pdo prepared statements 將不能起到防范的作用
- PDO::ATTR_EMULATE_PREPARES 啟用或禁用預(yù)處理語句的模擬。 有些驅(qū)動不支持或有限度地支持本地預(yù)處理。使用此設(shè)置強制PDO總是模擬預(yù)處理語句(如果為 TRUE ),或試著使用本地預(yù)處理語句(如果為 FALSE)。如果驅(qū)動不能成功預(yù)處理當前查詢,它將總是回到模擬預(yù)處理語句上。
- 不能讓占位符 ? 代替一組值,這樣只會獲取到這組數(shù)據(jù)的第一個值,
select * from table where userid in ( ? );
如果要用in來查找,可以改用find_in_set()實現(xiàn):
$ids = '1,2,3,4,5,6'; select * from table where find_in_set(userid, ?); - 不能讓占位符代替數(shù)據(jù)表名或列名,如:
select * from table order by ?; - 不能讓占位符 ? 代替任何其他SQL語法,如:
select extract( ? from addtime) as mytime from table;
總結(jié)
以上是生活随笔為你收集整理的php安全编程—sql注入攻击的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Eclipse更改系统主题
- 下一篇: [Java] System.array