一、SQL注入分類
按數據類型分
數字類型
後臺語句可能爲:
$id=$_POST['id']
select user,password from users where id=$id
字符類型
$id=$_POST['id']
後臺語句可能爲:select user,password from users where id='$id'
總結:
- 數字類型直接將後臺接收到用戶輸入的內容帶入到數據庫中執行;而字符型將接收到的內容添加到引號內然後進行執行。
- 字符型注入需要考慮語句的閉合問題,而數字類型則不存在
MySQL手工測試字符型閉合語句
select user,password from users where id='$id'
select user,password from users where id="$id"
select user,password from users where id=($id)
select user,password from users where id=('$id') 括號可以無限疊加
select user,password from users where id=("$id") 括號可以無限疊加
select user,password from users where id=(($id)) 括號可以無限疊加
可參考sqli-labs靶機進行測試學習
按注入位置分
GET方式注入
注入參數以GET方式進行提交
POST方式注入
注入參數以POST方式進行提交
基於cookie的注入
後臺接收cookie內的參數,在http的cookie字段中存在注入漏洞
基於http頭部的注入
後臺會接收referer或user-agent字段中的參數,http頭部中的referer、user-agent字段中存在注入漏洞
盲注
基於布爾的盲注
特點:網站頁面在輸入條件爲true和false的情況下會顯示不同,但頁面中沒有輸出。此時需要在SQL語句之後添加條件判斷。
猜解思路:
- 猜解數據庫:先構造條件判斷當前數據庫的名字長度,然後逐字猜解數據庫名。
- 猜解數據表:先構造條件判斷數據表的數量,然後逐個進行猜解,先猜解表名長度然後逐字猜解表名。
- 猜解數據列:指定數據庫中的指定表進行猜解字段,首先猜解字段的數目,然後逐個猜解字段
- 猜解內容:指定數據列,先查詢數據的條數,然後逐條猜解其中的內容
基於時間的盲注
特點:網站頁面在輸入條件爲真和爲假返回的頁面相同,但通過延時函數構造語句,可通過頁面響應時間的不同判斷是否存在注入
猜解思路:
類似基於布爾的盲注,只是將條件爲真轉換爲延時響應
常用函數
if(condition,A,B)
:若condition返回真則執行A,假則執行Bsubstr(str,A,B)
:字符串截取函數,截取str字符串從A位置開始,截取B個字符left(str,A)
:類似字符串截取函數,返回str字符串從左往右數的A個字符count(A)
:計算A的數目,常用與查詢數據表、數據列、數據內容的條數len(A)
:計算A的長度,常用於返回數據庫名、數據表名、數據列名的長度ascii(A)
:返回A的ascii碼,當逐字猜解限制單引號的輸入時,可以通過查詢ascii碼來繞過
基於UNION的注入
首先通過order by 進行判斷查詢參數的數目,然後構造union查詢,查看回顯。有時需要將前面參數名修改爲假的參數。如id=-10’ union select 1,2,查找頁面中1和2的位置,在頁面中顯示的數字的地方構造查詢的內容。
若頁面無回顯但報錯可以嘗試報錯注入
基於報錯的注入
常用函數:
updatexml(1,concat('~',SQL語句,'~'),1)
extractvalue(1,concat('~',(SQL語句)))
寬字節注入
寬字節注入的原理即爲數據庫的編碼與後臺程序的編碼不一致,數據庫中一個字符佔兩個字節,而後臺程序爲一個字符佔一個字節,當後臺程序對輸入的單引號的字符進行轉義時,通過在這些轉義的字符前輸入%bf然後將%bf’帶入後臺程序時會轉義爲%bf’,此時帶入數據庫中,數據庫將%bf\看作是一箇中文字符從而使用單引號將SQL語句進行閉合。
基於base64加解密注入
後臺程序在接收用戶輸入的參數後先進行base64解碼然後帶入到SQL語句中執行。所以這種類型的注入首先需要將payload進行base64加密
搜索型注入
當搜索關鍵字時,後臺SQL語句可能爲:select username from users where id='%$id%'
,此時構造閉合語句時需要考慮%的閉合
二、防禦
代碼層面
- 對用戶輸入的內容進行轉義(PHP中addslashes()、mysql_real_escape()函數)。
- 限制關鍵字的輸入(PHP中preg_replace()函數正則替換關鍵字),限制輸入的長度 。
- 使用SQL語句預處理,對SQL語句首先進行預編譯,然後進行參數綁定,最後傳入參數。
網絡層面
部署防火牆