SQLMAP的前世今生Part2 資料庫指紋識別
0x00 前言
談到SQL隱碼攻擊,那麼第一時間就會想到神器SQLMAP,SQLMap是一款用來檢測與利用的SQL隱碼攻擊開源工具。那麼SQLMap在掃描SQL的邏輯到底是怎樣實現的呢,接下來就探討下SQLMap的掃描邏輯,透過了解SQLMap的掃描邏輯打造一款屬於自己的SQL掃描工具。
0x01 SQLMAP的準備工作
SQLMAP在進行掃描之前會有一些其他的功能去確定當前的目標的一些有用的資訊,如防火牆的檢測,當檢測到有防火牆之後,進行SQL檢測時的判斷依據也會有所調整,如bool型別的盲注的時候,而其中heuristicCheckSqlInjection這一函式既會影響到接下來所要使用什麼樣的Payload進行測試,heuristicCheckSqlInjection翻譯過來的意思是啟發式SQL隱碼攻擊測試,那麼到底什麼是啟發式,具體作用到底是什麼呢,在我們經常使用SQLMAP的時候,有可能會出現以下的提示。
上面提示我們當前的目標資料庫版本好像是Oracle,而這上面的提示的依據就是根據這一個啟發式SQL隱碼攻擊測試也就是本文要介紹的heuristicCheckSqlInjection來決定的。SQLMAP中有許多的Payload,足以有幾百條,那麼如果全部Payload都測試一遍的話,無疑是一件很浪費時間的事情,除非Payload中的risk,clause,where欄位中加以過濾,還會以這一個根據資料庫的指紋來選擇所要測試的Payload。
heuristicCheckSqlInjection的主要作用可以分為以下幾點:
- 資料庫版本的識別。
- 絕對路徑獲取。
- XSS的測試
0x02 資料庫版本的識別
#!python
# Alphabet used for heuristic checks
HEURISTIC_CHECK_ALPHABET = ('"', '\'', ')', '(', ',', '.')
...
randStr = ""
while '\'' not in randStr:
randStr = randomStr(length=10, alphabet=HEURISTIC_CHECK_ALPHABET)
kb.heuristicMode = True
payload = "%s%s%s" % (prefix, randStr, suffix)
payload = agent.payload(place, parameter, newValue=payload)
page, _ = Request.queryPage(payload, place, content=True, raise404=False)
...
首先會從HEURISTIC_CHECK_ALPHABET中隨機抽取10個字元出現構造Payload,當然裡面的都不是些普通的字元,而且些特殊字元,當我們進行SQL隱碼攻擊測試的時候會很習慣的在引數後面加個分號啊什麼的,又或者是其他一些特殊的字元,出現運氣好的話有可能會暴出資料的相關錯誤資訊,而那個時候我們就可以根據所暴出的相關錯誤資訊去猜測當前目標的資料庫是什麼。
實際找個網站測試,打下碼,保護下。
http://***.***.***/datalist/default.aspx/article?category_id=1051
那麼經過while '\'' not in randStr:
後生成了隨機的字元,然後就是發包檢測返回的資料了。
如下圖:
其實熟悉SQL隱碼攻擊的人也知道這是一個Oracle的一個錯誤資訊,那麼接下來看看SQLMAP到底是怎樣去判斷的。
位於./lib/request/connect.py
中的getPage函式,大約在598行。
#!python
def getPage(**kwargs):
...
processResponse(page, responseHeaders)
...
其中processResponse會呼叫到./lib/parse/html.py
中的htmlParser
函式,這一個函式就是根據不同的資料庫指紋去識別當前的資料庫究竟是什麼。
#!python
def htmlParser(page):
"""
This function calls a class that parses the input HTML page to
fingerprint the back-end database management system
"""
xmlfile = paths.ERRORS_XML
handler = HTMLHandler(page)
parseXmlFile(xmlfile, handler)
if handler.dbms and handler.dbms not in kb.htmlFp:
kb.lastParserStatus = handler.dbms
kb.htmlFp.append(handler.dbms)
else:
kb.lastParserStatus = None
# generic SQL warning/error messages
if re.search(r"SQL (warning|error|syntax)", page, re.I):
handler._markAsErrorPage()
return handler.dbms
最終實現的的其實是HTMLHandler
這個類,而paths.ERRORS_XML
這一變數的就是SQLMAP用來識別的指紋配置檔案路徑,位置在於./xml/errors.xml
中。
#!html
<!-- Oracle -->
<dbms value="Oracle">
<error regexp="\bORA-[0-9][0-9][0-9][0-9]"/>
<error regexp="Oracle error"/>
<error regexp="Oracle.*Driver"/>
<error regexp="Warning.*\Woci_.*"/>
<error regexp="Warning.*\Wora_.*"/>
</dbms>
這一配置檔案的比較簡單,其實也就是一些對應資料庫的正則。SQLMAP在解析errors.xml的時候,然後根據regexp中的正則去匹配當前的頁面資訊然後去確定當前的資料庫。
#!python
class HTMLHandler(ContentHandler):
"""
This class defines methods to parse the input HTML page to
fingerprint the back-end database management system
"""
def __init__(self, page):
ContentHandler.__init__(self)
self._dbms = None
self._page = page
self.dbms = None
def _markAsErrorPage(self):
threadData = getCurrentThreadData()
threadData.lastErrorPage = (threadData.lastRequestUID, self._page)
def startElement(self, name, attrs):
if name == "dbms":
self._dbms = attrs.get("value")
elif name == "error":
if re.search(attrs.get("regexp"), self._page, re.I):
self.dbms = self._dbms
self._markAsErrorPage()
可以發現當前返回的頁面資訊命中了<error regexp="\bORA-[0-9][0-9][0-9][0-9]"/>
這一條正規
到此SQLMap就可以確定資料的版本了,從而選擇對應的測試Payload,減少SQLMAP的掃描時間。
0x03 絕對路徑獲取與XSS檢測
相比指紋識別,獲取絕對路徑的功能模組相對簡單,利用正則匹配尋找出絕對路徑。
#!python
def parseFilePaths(page):
"""
Detects (possible) absolute system paths inside the provided page content
"""
if page:
for regex in (r" in <b>(?P<result>.*?)</b> on line", r"(?:>|\s)(?P<result>[A-Za-z]:[\\/][\w.\\/]*)", r"(?:>|\s)(?P<result>/\w[/\w.]+)"):
for match in re.finditer(regex, page):
absFilePath = match.group("result").strip()
page = page.replace(absFilePath, "")
if isWindowsDriveLetterPath(absFilePath):
absFilePath = posixToNtSlashes(absFilePath)
if absFilePath not in kb.absFilePaths:
kb.absFilePaths.add(absFilePath)
而XSS的檢測程式碼位於889行中:
#!python
# String used for dummy XSS check of a tested parameter value
DUMMY_XSS_CHECK_APPENDIX = "<'\">"
...
value = "%s%s%s" % (randomStr(), DUMMY_XSS_CHECK_APPENDIX, randomStr())
payload = "%s%s%s" % (prefix, "'%s" % value, suffix)
payload = agent.payload(place, parameter, newValue=payload)
page, _ = Request.queryPage(payload, place, content=True, raise404=False)
paramType = conf.method if conf.method not in (None, HTTPMETHOD.GET, HTTPMETHOD.POST) else place
if value in (page or ""):
infoMsg = "heuristic (XSS) test shows that %s parameter " % paramType
infoMsg += "'%s' might be vulnerable to XSS attacks" % parameter
logger.info(infoMsg)
...
最後根據輸入的字元是否留著頁面上,如果存在就提示有可能擁有XSS漏洞。
0x04 總結
至此heuristicCheckSqlInjection的功能也介紹的差不多了,透過具體瞭解SQLMAP的一些掃描規則又或者是思路,可以讓我們根據具體的情況去配置SQLMAP又或者編寫自己的SQL Fuzz系統,其中可以透過編輯errors.xml這一指資料紋配置來增強SQLMAP的嗅探能力,從而打造更強大的神器了。
相關文章
- 資料庫的前世今生2020-04-06資料庫
- SQLMap的前世今生(Part1)2020-08-19SQL
- 知物由學 | iOS裝置指紋的前世今生2020-11-27iOS
- [Android]BMPrinter 指紋識別庫2018-09-07Android
- 圖資料庫專案DGraph的前世今生2019-02-28資料庫
- 重新學習MySQL資料庫開篇:資料庫的前世今生2019-08-24MySql資料庫
- Android 指紋識別,指紋支付demo2018-08-30Android
- CMS指紋識別2024-06-17
- 基礎資料平臺的前世今生2020-11-14
- 生物特徵識別之指紋識別,偽造,指紋裝置缺陷設計2020-08-19特徵
- 指紋識別將走向何方?2019-07-16
- 如何設計APP的指紋識別功能2018-05-10APP
- RabbitMQ的前世今生2018-12-06MQ
- InfiniBand 的前世今生2023-11-03
- MySQL 的前世今生2020-02-13MySql
- Mybatis的前世今生2019-04-19MyBatis
- Unicode的前世今生2019-02-20Unicode
- Dubbo的前世今生2022-02-18
- Serverless 的前世今生2022-11-24Server
- IPD的前世今生2021-09-23
- CRM的前世今生2020-12-29
- DBHub的前世今生2021-01-01
- 【UV統計】海量資料統計的前世今生2020-12-13
- 【中國資料庫前世今生】資料儲存管理的起源與現代資料庫發展啟蒙2024-08-20資料庫
- 關於 sqlmap 注入的疑惑,sqlmap 是如何拿到資料庫資料的呢?2020-11-19SQL資料庫
- win10指紋識別登陸怎麼用_win10指紋識別登陸使用教程2020-04-22Win10
- 驗證碼的前世今生:從圖文識別到無感驗證2020-05-13
- 分庫分表系列:分庫分表的前世今生2022-03-19
- Webpack前世今生2020-07-22Web
- React ref 的前世今生2018-07-26React
- React Portal的前世今生2018-03-13React
- 遊戲的前世今生2019-12-23遊戲
- HTTP/2.0的前世今生2019-03-14HTTP
- 元件化的前世今生2021-09-09元件化
- 聊聊 HTAP 的前世今生2023-02-23
- 聊聊ChatGPT的前世今生2023-02-09ChatGPT
- 外掛的前世今生2020-12-20
- android 簡單實現指紋識別功能2018-09-28Android