SQLMAP進階使用
0x00 背景
首先在drops上搜尋下sqlmap相關的文章:
介紹的比較全了,但是對於sqlmap的指令碼擴充套件部分沒有提及,例如自定義payload,自定義繞過指令碼等等。
0x02 自定義payload指令碼
2.1 需求
我們先寫一個比較全的select語句:
#!sql
select * from users where user_id in(1,2,3,[4]) and first_name like '%[t]%' and second_name=[’b’] group by [first_name] order by [1] [desc] limit [1]
語句中[]中的內容都是查詢中可能存在的注入點。
那麼問題來了:
1):這些注入點裡面哪些是sqlmap在預設level下就能夠識別的?
2):不能夠在預設級別下識別的注入點,sqlmap在level=多少的時候能否識別?
3):sqlmap識別不了的時候怎麼辦?
以order by型別的注入來看,order by [1][1]
這個引數在設定level=3的時候會被sqlmap檢測出來(這裡需要注意的在01_boolean_blind.xml
檔案中,如果level欄位設定的是2,在測試的時候需要設定比level高的才可以被識別,如rlike order by
注入設定的level值為2,我在命令列使用sqlmap引數的時候需要設定level=3)
但是order by 1 [desc]
,在設定level=3的時候也無法識別,也許你會說新增suffix和prefix就可以了,確實是這樣,但是現在的選手一般都會選擇開web代理,然後呼叫sqlmap介面去檢查,因此這裡對於sqlmap的要求就高了.
第一:sqlmap要能夠檢測出url的引數存在注入點;
第二:測試的效率要高[不能夠將level設定的很高];設定level高的情況下,會有更多的請求。
現在看來自己將payload編寫為sqlmap可用的payload即可。
2.2 說明
Sqlmap在執行之後會載入讀取xml檔案,並且將結果儲存到conf.tests中,如下圖:
這部分payload會在會在checkSqlInjection中使用:
接下來只要知道如何使用這部分payload以及xml中各個欄位是什麼意思即可。
首先詳細看一下payload中欄位:
title欄位:payload test起的名字; 譬如我們給自己的payload起的名字為:
#!sql
MySQL boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause (desc-mayikissu)
style欄位:sql注入的型別sql注入分了如下型別:
型別1:盲注 我們order by型別屬於盲注,因此我們新增stype的值為1.
型別2:錯誤型別注入
型別3:內聯注入
型別4:多語句查詢注入
型別5:時間注入
型別6:聯合查詢注入
level欄位:sqlmap對於每一個payload都有一個level級別,level級別越高表示檢查的payload個數就越多。 譬如我們自定義個level設計的為2,因此只有在使用在命令列使用level》2的時候,才會使用我們的payload進行檢測。
risk欄位:風險等級,有多大機率獲取破壞資料。值有1,2,3,分別表示低中高。預設的risk為1,預設檢測所有風險級別的payload。 該欄位影響不大。
clause欄位:payload在哪個語句裡生效,差不多意思就是這個payload用在sql語句的哪個位置。可用的值:
0: Always
1: WHERE / HAVING
2: GROUP BY
3: ORDER BY
4: LIMIT
5: OFFSET
6: TOP
7: Table name
8: Column name
我們這裡測試的是order by,此處clause的欄位設定為3,經過測試這裡的值可以混用的,關鍵看sql語法。
where欄位:
where欄位我理解的意思是,以什麼樣的方式將我們的payload新增進去。
1:表示將我們的payload直接新增在值得後面[此處指的應該是檢測的引數的值] 如我們寫的引數是id=1,設定<where>
值為1的話,會出現1後面跟payload
2:表示將檢測的引數的值更換為一個整數,然後將payload新增在這個整數的後面。 如我們寫的引數是id=1,設定<where>
值為2的話,會出現[數字]
後面跟payload
3:表示將檢測的引數的值直接更換成我們的payload。 如我們寫的引數是id=1,設定<where>
值為3的話,會出現值1直接被替換成了我們的payload。
我們的場景是order by 1 [desc]
,此處我們直接將desc更換成我們的payload即可。
vector欄位: vector欄位表示的是payload向量,類似於一個模型的感覺。
#!sql
,IF([INFERENCE],[ORIGVALUE],(select 1 from information_schema.tables))
此處為我設定的vector,INFERENCE為條件,ORIGVALUE為引數原始的值,如我傳入的id=1或者desc,1和desc即為原始值,此處無所謂,在我的場景裡只要為一個值即可。
request和response理解為請求的時候payload值,以及請求的值與什麼樣的值進行對比。 請求的payload為:
#!sql
,IF([RANDNUM]=[RANDNUM],[ORIGVALUE],(select 1 from information_schema.tables))
響應的對比payload為:
#!sql
,IF([RANDNUM]=[RANDNUM1],[ORIGVALUE],(select 1 from information_schema.tables))
大致理解就是對比if條件不等和相等,如此來進行盲注。
瞭解這些引數之後,接下來我們需要知道sqlmap如何將這樣自定義的payload組合起來即可。於是我們跟蹤一下checksqlinjection這個函式,即可知道sqlmap是如何將payload組合起來的了。
在函式中有一個重要的引數,boundary引數,這個引數是從xml目錄下的boundaries.xml檔案中讀取出來的。每個boundary的格式如下圖內容:
其中level,clause以及where表達的意思和payload中相關標籤表達的意思是一樣的。 標籤ptype表示引數的型別,prefix表示新增內容的字首,suffix表示新增內容的字尾。
核心的部分是獲取payloads.xml中的每一個payload,然後獲取payload中的引數與boundary.xml中獲取的引數進行比較。大致流程如下:
獲取payload.xml檔案中的每一個payload。
獲取boundary.xml檔案中的每一個boundary。
比較判斷payload中的clause是否包含在boundary的clause中,如果有就繼續,如果沒有就直接跳出。
比較判斷payload中的where是否包含在boundary的clause中,如果有就繼續,如果沒有就直接跳出。
將prefix和suffix與payload中的request標籤的內容拼接起來儲存到boundpayload中。
最後就是傳送請求,然後將結果進行比較了。
Ps.因此我們在設計自定義指令碼的時候需要注意的幾個地方,payload中的clause標籤,level標籤,where標籤,vector標籤以及reqeust和response標籤。基本上理解並設計好這些標籤,就能夠自定義指令碼了。
2.3 實現
Sqlmap的相關payload在目錄./sqmap/xml/payloads/目錄下,新版目錄下會有一個payloads的目錄,裡面有各種型別的sql注入的payload,選取盲注的xml,在其中編寫一個test節點,內容如下圖:
(相關引數的解釋在後面描述)
然後自己建立一個存在order by 1 [desc]
這種型別sql注入的php頁面:
這時候用我們修改過的sqlmap去傳送,檢視結果:
0x03 自定義bypass指令碼
3.1 需求
在./sqlmap/tamper目錄下,設計了很多的指令碼,這些指令碼是用來對於請求的payload進行修改的,但是往往有一些情況這些預定義的指令碼不能夠滿足我們的需求,例如有一些waf對於逗號進行了過濾,又如有時候我們需要使用%a0去替換payload中的空白等等情況。這時候就需要我們自己新增指令碼來完成工作了。
3.2 說明
要知道如何新增自定義指令碼,我們需要了解的是
第一:tamper指令碼是什麼時候被sqlmap載入的;
第二:tamper指令碼是什麼時候被sqlmap呼叫的;
第三:tamper指令碼的裡的內容有什麼樣的規範;
問題一:tamper指令碼是什麼時候被sqlmap載入的
我們去看一下sqlmap的原始碼,大致邏輯是這樣
main()->init()->_setTamperingFunctions()
在_setTamperingFunctions
函式中載入了我們配置的tamper函式。然後會把tamper函式新增到了kb.tamperFunctions
裡面以被後續使用。
這樣看來要自定義的話這個指令碼中得有個tamper函式,然後就是編寫tamper函式的內
問題二:tamper指令碼是什麼時候被sqlmap呼叫的
tamper指令碼在queryPage函式中被呼叫,queryPage函式是用來請求頁面內容,在每次傳送請求之前,先會將payload進行tamper函式處理。下圖為呼叫between.py的指令碼。
問題三:tamper指令碼的裡的內容有什麼樣的規範
我們隨機選擇一個指令碼,該指令碼為base64encode.py,檢視指令碼中的tamper內容:
可以看到內容非常簡單,將payload的內容內容做了base64編碼然後直接返回。Tamper有兩個引數第一個引數payload即為傳入的實際要操作的payload,第二個引數**kwargs為相關httpheader。譬如你想插入或則修改header的時候可以用到。
邏輯流程弄清楚之後,很容易編寫自己的tamper指令碼了。
3.3 實現
以使用%a0替換空格的指令碼為例,在tamper目錄下建立space2ao.py指令碼,稍微修改下指令碼:
使用sqlmap傳送請求,去檢視下web日誌:
Ps.感覺很容易的樣子,這裡不演示如何bypass逗號的情況,下面換一個方式來使sqlmap bypass逗號被過濾的情況。
0x04 自定義query函式
在做測試的時候往往還會有一些情況,如mid函式被過濾了,逗號被過濾了等等。Sqlmap是機器操作,如果被過濾了一些函式,指令碼肯定就無法走後面的流程了。此時我們可以直接修改相關的querystring(xml中的相關內容),如我們可以將substr(expression,start,length)
替換成substr(expression from start for length)
。
這些內容在sqlmap/xml
目錄下的queries.xml目錄中。截圖下mysql標籤中的一些內容:
這個inference看起來就是用來猜欄位用的,而且之前我們在第一篇自定義過這個[inference欄位的],是不是我們將
ord(mid((%s),%d,1))>%d
更換為
ord(mid((%s) from %d for1))>%d
就可以了呢。
我們修改之後,跟蹤下payload的值是否更改了:
檢視下是否能夠爆出密碼:
檢視下web日誌,是否是傳送的那樣,解碼之後結果可以看到mid的逗號已經被修改。
這樣我們就可以讓mid函式沒有逗號了。其他的可以參考去修改queries中的相關內容就可以了。
0x05 防禦sqlmap
經過一番折騰,sqlmap可以比想象中更厲害了呢,目前為止很多選手都會用著sqlmap的外掛,或者是原版的sqlmap,亦或是修過過的sqlmap。如何防禦sqlmap呢:
1):大眾的防禦方法,sqlmap在傳送請求的時候,http的user-agent都會自帶sqlmap的,可以做協議解析之後,獲取user-agent,然後來判斷。不過很多測試選手都會使用sqlmap的引數對其進行修改。
2):之前除錯程式的時候看到過如下內容(之前在zone裡發表過):
http://127.0.0.1?id=1..]"')[.]"
於是就跑去看了看sqlmap的原始碼:
發現在checks.py的檔案裡面有一個函式名稱為heuristicCheckSqlInjection() 裡面有段程式碼:
#!python
while '\'' not in randStr:
randStr = randomStr(length=10, alphabet=HEURISTIC_CHECK_ALPHABET)
然後我們去檢視randomStr,此函式在common.py下,相關程式碼如下:
#!python
def randomStr(length=4, lowercase=False, alphabet=None):
"""
Returns random string value with provided number of characters
>>> random.seed(0)
>>> randomStr(6)
'RNvnAv'
"""
if alphabet:
retVal = "".join(random.choice(alphabet) for _ in xrange(0, length))
elif lowercase:
retVal = "".join(random.choice(string.ascii_lowercase) for _ in xrange(0, length))
else:
retVal = "".join(random.choice(string.ascii_letters) for _ in xrange(0, length))
return retVal
然後去檢視了HEURISTIC_CHECK_ALPHABET
,值為('"', "'", ')', '(', '[', ']', ',', '.')
因此得到這樣的結論,這串randStr的值為一個十個隨機字元的長度字串,其中至少包含',隨機字串的內容在('"', "'", ')', '(', '[', ']', ',', '.')
裡。
這樣的規律是可以使用正規表示式寫出規則的,而且重複的機率應該不高,可以起到一定的防禦效果。
0x06 結尾
文章主要是對於最近學習的一個總結,用過之後感覺sqlmap的強大之處。對於現在自動化掃描的工具越來越多,sql自動掃描肯定也是被重視的地方。一來如何能夠識別更多的url,二來如何提高sql的識別準確率和效率,這些都是必須要考慮的地方。Sqlmap是個很厲害的工具,我們需要更好的使用它。
相關文章
- sqlmap 進階 (一)2019-03-30SQL
- sqlmap的使用2018-07-24SQL
- Sqlmap使用教程2019-07-01SQL
- sqlmap使用,配合Burpsuite2024-07-08SQLUI
- sqlmap使用手冊2022-03-04SQL
- sqlmap簡單使用方法2024-04-22SQL
- sqlmap使用者手冊2020-08-19SQL
- Celery 進階使用2020-12-29
- sqlmap使用者手冊[續]2020-08-19SQL
- Exceptionless(二) - 使用進階2019-06-29Exception
- SQLmap常用命令使用詳解2024-06-04SQL
- chrome devtools使用進階——Sources2018-09-06Chromedev
- git-rebase進階使用2019-07-30Git
- css進階less的使用2018-04-27CSS
- Zabbix監控使用進階2020-12-07
- 使用sqlmap中tamper指令碼繞過waf2020-08-19SQL指令碼
- 辦公進階:HoudahSpot使用教程2020-08-22
- Hadoop進階命令使用介紹2020-07-13Hadoop
- tar命令基本、進階使用指北2020-05-03
- CSS使用的一些小技巧/高階進階2019-03-04CSS
- 聊聊wireshark的進階使用功能2023-09-22
- HTML5進階FileReader的使用2019-07-27HTML
- 【C進階】#error和#line使用分析2021-12-26Error
- 【超詳細】安全測試===sqlmap使用心得(零)2021-12-22SQL
- SQLMAP 例項COOKBOOK2020-08-19SQL
- python-進階教程-使用物件屬性進行排序2018-12-09Python物件排序
- Python3進階——使用PyMySQL操作MySQL2018-07-25PythonMySql
- Scanner的進階使用——基礎計算2024-08-11
- flask 專案中使用 bootstrapFileInput(進階篇)2021-09-09Flaskboot
- 【Linux進階】使用grep、find、sed以及awk進行文字操作2021-06-22Linux
- SpreadJS使用進階指南 - 使用 NPM 管理你的專案2018-06-21JSNPM
- NSOperation的進階使用和簡單探討2018-11-24
- NSThead的進階使用和簡單探討2018-11-15
- Redux 進階 -- 編寫和使用中介軟體2018-04-23Redux
- stable diffusion ControlNet使用介紹與進階技巧2024-07-02
- 【C進階】21、巨集定義與使用分析2021-12-23
- 二、RabbitMQ 進階特性及使用場景 [.NET]2021-07-04MQ
- SQL隱碼攻擊 - sqlmap聯動burpsuite之burp4sqlmap++外掛2024-03-12SQLUI