一、為什么會有sql注入
是用戶輸入的內容在服務器中能夠被拼接查詢,從而輸出惡意用戶期望的內容,那么要防止SQL注入,就是阻止惡意用戶輸入的惡意信息被數據庫執行并且輸出。
1. 對于數字型注入,不需要單引號個的情況下
可以將payload跟在參數后邊,不受過濾和轉義的影響
$id=$_POST['id'];
$sql = select username from users where id= $id union select database();
2. 寬字節注入(但是要使用gbk編碼)
在使用gbk編碼時,系統會認為兩個字符是一個漢字的編碼(前一個字符必須大于128)。
輸入%df%27時首先經過上面提到的單引號轉義變成了%df%5c%27(%5c是反斜杠\),之后在數據庫查詢前由于使用了GBK多字節編碼,即在漢字編碼范圍內兩個字節會被編碼為一個漢字。然后MySQL服務器會對查詢語句進行GBK編碼即%df%5c轉換成了漢字“運”,而單引號逃逸了出來
3. 使用編碼的形式
查詢的數據在經過webserver時會被解碼一次
id=1%2527 --->webserver --> id=1%27 --> urldecode--> 1'
4. 二次注入
二次注入漏洞字面上理解可能就是結合兩個注入漏洞點實現sql注入的目的,但是這其中還有幾個細節需要講解一下。首先,第一個注入點因為經過過濾處理所以無法觸發SQL注入漏洞,比如addslashes函數,將單引號等字符轉義變成\’。但是存進數據庫后,數據又被還原了,也就是反斜杠沒了,在這種情況下,如果能發現一個新的注入同時引用了被插入了的數據庫數據,就可以實現閉合新發現的注入漏洞引發漏洞。
二、如何防止SQL注入
通過上邊的四種方式完美的繞過了反斜杠和單引號轉義是否能防止SQL注入的問題,哪如何能防止SQL注入呢?
1、所有的查詢語句都使用數據庫提供的參數化查詢接口,參數化的語句使用參數而不是將用戶輸入變量嵌入到SQL語句中。當前幾乎所有的數據庫系統都提供了參數化SQL語句執行接口,使用此接口可以非常有效的防止SQL注入攻擊。
2、對進入數據庫的特殊字符(’”<>&*;等)進行轉義處理,或編碼轉換。
3、確認每種數據的類型,比如數字型的數據就必須是數字,數據庫中的存儲字段必須對應為int型。
4、數據長度應該嚴格規定,能在一定程度上防止比較長的SQL注入語句無法正確執行。
5、網站每個數據層的編碼統一,建議全部使用UTF-8編碼,上下層編碼不一致有可能導致一些過濾模型被繞過。
6、嚴格限制網站用戶的數據庫的操作權限,給此用戶提供僅僅能夠滿足其工作的權限,從而最大限度的減少注入攻擊對數據庫的危害。
7、避免網站顯示SQL錯誤信息,比如類型錯誤、字段不匹配等,防止攻擊者利用這些錯誤信息進行一些判斷。