漏洞掃描技巧篇 「Web 漏洞掃描器」

0x00 前言

之前我們簡單介紹了一下掃描器中爬蟲的部分,接下來將繼續介紹掃描器中一些我們認為比較有趣的技巧。

0x01 編碼/解碼/協議

在很久以前有人提問 AMF 格式的請求怎麼進行檢測,或者有什麼工具可以檢測。

既然我們要講解的是 Web 漏洞掃描器,那麼就先假設是 AMF over HTTP (這裡並不需要你瞭解 AMF,你只需要知道 AMF 是一種數據格式類型就行)。

假設我們需要測試一個 AMF 格式數據的 SQL 注入問題,那麼按照通常的思路就是在 SQL 注入模塊中:

1.先解析 HTTP 中 AMF 格式數據

2.然後在測試參數中填寫 payload

3.重新封裝 AMF 格式數據

4.發送 HTTP 請求

偽代碼如下:

<code>1req = {"method": "POST", "url": "http://fatezero.org", "body": "encoded data"}
2data = decode_amf(req["body"])
3for key, value in data.items():
4    d = copy.deepcopy(data)
5    d[key] = generate_payload(value)
6    body = encode_amf(d)
7    requests.request(method=req["method"], url=req["url"], body=body)
/<code>

整個流程下來沒什麼問題,但是如果又來了一個 X 協議(X over HTTP),那麼我們就得繼續修改 SQL 注入模塊以便支持這種 X 協議,但是掃描器中可不是隻有 SQL 注入檢測模塊,還有其他同類模塊,難道每加一個新協議我還得把所有檢測模塊都改一遍?

所以我們需要把這些協議解析和封裝單獨抽出來放在一個模塊中。

偽代碼如下:

<code> 1# utils.py
 2def decode(data):
 3    if is_amf(data):
 4        data = decode_amf(data)
 5
 6    if is_X(data):
 7        data = decode_X(data)
 8
 9    # 遞歸 decode
10    for i in data:
11        data[i] = decode(data[i])
12
13    return data
14
15
16# detect_module.py
17req = {"method": "POST", "url": "http://fatezero.org", "body": "encoded data"}
18data = decode(req["body"])
19for key, value in data.items():
20    d = copy.deepcopy(data)
21    d[key] = generate_payload(value)
22    body = encode(d)
23    requests.request(method=req["method"], url=req["url"], body=body)
/<code>

上面的遞歸 decode 主要是為了解碼某種格式的數據裡面還有另外一種格式的數據,雖然看起來這種場景比較少見,但是仔細想一下 multipart 帶著 json,json 裡的字符串是另外一個 json 字符串,是不是又覺得這種情況也並不少見。

那 encode/decode 剝離出來就可以了嗎?請注意到上面偽代碼使用了 requests. request 發送請求,那如果某天需要我們去測試 websocket 協議,是不是又得在檢測模塊中多加一套 websocket client 發送請求?

所以我們也需要將具體的網絡操作給剝離出來,具體的協議類型直接由上面來處理,檢測模塊只需要關注具體填寫的 payload。

偽代碼如下:

<code>1for key, value in x.items():
2    data.reset()
3    x[key] = generate_payload(value)
4    x.do()  # 負責將數據重新組裝成原來的格式,並按照原始協議發送
5
6   # check
/<code>

因為每個檢測模塊的檢測依據大致就幾種:

  • 返回內容
  • 消耗時間 (time based)
  • 另外一條信道的數據 (比方說 dnslog)

所以即便是我們將網絡操作剝離出來也不會影響檢測的效果。

在編寫檢測模塊的時候,編寫者可以不用關心基礎協議是什麼,怎麼對數據編碼解碼,只用關心根據 value 生成 payload 並填寫到相對應的 key 中。

假如某天出現了這麼一種流行編碼格式 http://www.a.com/key1, value1,key2,value2,那我們所有的檢測模塊也無需修改,僅僅需要在上一層再添加一套 encode/decode 操作即可。假如某天出現了一種比較流行的協議,我們也僅需要在上一層提供一套 client 即可。檢測模塊的工作就僅僅剩下生成並填寫 payload。

0x02 PoC 分類

在 2014 年的時候,我做了大量的競品分析,包括使用逆向工程逆向商業的 Acunetix WVS, HP Webinspect, IBM AppScan, Netsparker 掃描邏輯,也包括閱讀開源的 w3af, arachni 代碼。

如果不談掃描質量,只關注整體項目設計以及產品中使用到的猥瑣技巧,那麼其中最讓我眼前一亮的當屬 AWVS,接下來我將詳細介紹一下我從 AWVS 中學習到的 PoC 分類。

PoC 分類:

類型描述PerServer用於檢測 Web Server 級別中存在的漏洞,比方說各種中間件,Web 框架的漏洞PerFile用於檢測某個文件中是否存在漏洞,比如對應文件的備份,Bash RCE 等PerFolder用於檢測某個目錄中是否存在漏洞,比如敏感信息的洩漏,路徑中的 SQL 注入等PerScheme用於檢測某個參數中是否存在漏洞,比如 SQL 注入,XSS 等PostCrawl在爬蟲結束之後啟動,直接使用爬蟲的資源進行檢測PostScan在掃描結束之後啟動,用於檢測二階注入,存儲 XSS等WebApps用於檢測比較常用的 Web 應用的漏洞

大致的流程圖如下:

漏洞掃描技巧篇 「Web 漏洞掃描器」

在獲取到爬蟲資產,對相關資產格式化之後,便下發到各個不同類型的 PoC 中進行檢測,這樣做的好處是分類明確,覆蓋大多數檢測階段,也避免為了減少重複請求的下發而需要額外記錄中間狀態的行為。

0x03 IAST

AWVS 有個比較有趣的功能 AcuMonitor ,也就大家熟知的 dnslog、反連平臺。在 2014 年看到 AWVS 的這個功能時,就建議 WooYun 出個類似的功能,也就是 cloudeye,tangscan 也就算是國內比較早使用這種技術的掃描器,當然後續又出現了各種類似 cloudeye 的項目,自然而然也出現了各種使用該技術的掃描器。

不過今天我們不打算繼續介紹 AcuMonitor,而是介紹另外一個也很有趣的功能 AcuSensor 。AcuSensor 就是IAST,只要稍微瞭解過 Web 漏洞掃描器的,都應該會知道 IAST 是幹啥的。那為什麼我要單獨拎出來講這個呢?

主要是因為 AcuSensor 的實現方式非常有趣。AcuSensor 提供了 Java、 .NET、PHP 這三個語言版本,其中比較有趣的是 PHP 版本的實現。

PHP版本的AcuSensor使用方法是下載一個acu_phpaspect.php文件,再通過 auto_prepend_file 加載這個文件, 眾所周知,PHP 是不能改直接 hook PHP 內置函數的,那麼單單依靠一個 PHP 腳本,AcuSensor是如何做到類似 IAST 功能的呢?

很簡單,直接替換所有關鍵函數。嗯,真的就那麼簡單。

我們來詳細介紹一下這個過程,在 acu_phpaspect.php 中:

1.獲取用戶實際請求的文件內容

2.檢查一下有沒有相關 cache,如果有 cache 那麼直接加載執行 cache,然後結束

3.使用 token_get_all獲取所有 token遍歷每一個 token,對自己感興趣的函數或者語句使用自己定義的函數進行 wrap 並替換

4.將替換後的內容保存到 cache 中並使用 eval 執行

5.__halt_compiler中斷編譯

舉個具體的例子:

<code>1/<code>

經過 acu_phpaspect.php 轉換之後:

<code>1/<code>

整個過程簡單粗暴有效,這樣做的優點在於:

  • 實現簡單,只需要編寫 PHP 即可
  • 安裝簡單,無需安裝擴展,只需修改配置文件可以
  • 兼容性強,比較容易兼容性各種環境,各種版本 PHP

如果有意向去做 IAST 或者想做類似我的 prvd http://github. com/fate0/prvd項目,但又不太喜歡寫 PHP 擴展,那麼我強烈建議你完整的看一遍 PHP 版本 AcuSensor 的實現。如果對自己實現的檢測邏輯效率比較自信的話,甚至可以基於這個原理直接實現一個 PHP 版本的 RASP 項目。

0x04 限速

在 Web 漏洞掃描器中,無論作為乙方的商業產品、甲方的自研產品,限速都是一個至關重要的功能,甚至可以說如果你的掃描器沒有限速功能,那壓根就不能上線使用。接下來我們將介紹一下在掃描器中限速的幾種方法。

1.代理

使用代理做限速功能,將所有執行掃描任務的 worker 的測試流量全轉發proxy 服務器上:

漏洞掃描技巧篇 「Web 漏洞掃描器」

由 proxy 服務器統一調度發送測試請求頻率,直接使用 proxy 方案優點是可以兼容之前沒做限速功能的掃描器,缺點是所有基於 time based 的檢測均無效(當然也可以讓 proxy 返回真正的響應時間來進行判斷,不過仍需要修改檢測模塊),也不允許在檢測模塊中加入超時設置。

2.雙重隊列

另外一種方法是使用雙重隊列實現限速功能,流程圖如下:

漏洞掃描技巧篇 「Web 漏洞掃描器」

1.worker1 從隊列中取到名為 target1 的任務

2.worker1 從 target1 隊列中取出和 target1 相關的任務

3.默認單併發執行和 target1 相關任務,根據設置的 QPS 限制,主動 sleep 或者增加併發

這種方案的缺點是掃描器設計之初的時候就得使用這種方法,優點是每個併發可以穩定的和遠程服務器保持鏈接,也不影響掃描功能。

0x05 漏洞檢測

實際上這一節並不會講具體某個漏洞檢測方法,只是簡單談一下漏掃模塊每個階段該乾的事情。

項目之初,沒有相關積累,那麼可以選擇看一下 AWVS 的檢測代碼,雖然說網上公開的是 10.5 的插件代碼,但其實從 8.0 到 11 的插件代碼和 10.5 的也差不多,無非新增檢測模塊,修復誤漏報的情況,也可以多看看 SQLMap 代碼,看看檢測邏輯,但是千萬不要學習它的代碼風格。從這些代碼中可以學習到非常多的小技巧,比如動態頁面檢測,識別 404 頁面等。看代碼很容易理解相關的邏輯,但我們需要去理解為什麼代碼這樣處理,歷史背景是什麼,所以多用 git blame。

到了中期,需要提升漏洞檢測的精準度,漏洞檢測的精準度是建立在各種 bad case 上,誤報的 case 比較容易收集和解決,漏報的 case 就需要其他資源來配合。作為甲方如果有漏洞收集平臺,那麼可以結合白帽子以及自己部門滲透團隊提交的漏洞去優化漏報情況。

如果掃描器是自己的一個開源項目的話,那麼就必須適當的推廣自己的項目,讓更多的人去使用、反饋,然後才能繼續完善項目,從而繼續推廣自己的項目,這是一個循環的過程。總而言之,提升漏洞檢測的精準度需要兩個條件:1. bad case,2. 維護精力

到了後期,各種常規的漏洞檢測模塊已經實現完成,也有精力持續提升檢測精準度,日常漏洞 PoC 也有人員進行補充。

那麼事情就結束了麼?

不,依舊有很多事情我們可以去做,掃描器的主要目標是在不影響業務的情況下,不擇手段的發現漏洞,所以除了常規的資產收集方式之外,我們還可以從公司內部各處獲取資產相關的數據,比方說從 HIDS 中獲取所有的端口數據、系統數據,從流量中或業務方日誌中獲取 url 相關數據等。

當然除了完善資產收集這塊,還有輔助提升檢測效果的事情,比如說上面提到的 AcuSensor,這部分事情可以結合公司內部的 RASP 做到同樣效果,還有分析 access log、數據庫 log 等事情。總的來說,做漏掃沒有什麼條條框框限制,只要能發現漏洞就行。

以上都是和技術相關的事情,做漏掃需要處理的事情也不僅僅只有技術,還需要去搞定詳細可操作的漏洞描述及其解決方案,彙報可量化的指標數據,最重要的是擁有有理有據、令人信服的甩鍋技巧


分享到:


相關文章: