Zimbra xxe+ssrf導致getshell

Zimbra xxe+ssrf to RCE

前言

2019年3月13號,國外一名安全研究員在他的博客上公佈了zimbra的這起漏洞,但是其中並未提到一些漏洞的利用細節,在此我將整個漏洞的利用過程進行復現。
原文鏈接:https://blog.tint0.com/2019/03/a-saga-of-code-executions-on-zimbra.html#href1_ret

影響版本

  • Zimbra < 8.7.1 攻擊者可以在無需登錄的情況下,實現getshell
  • Zimbra<8.8.11 在服務端使用Memcached做緩存的情況下,經過登錄認證後的攻擊者可以實現遠程代碼執行

預防:由於zimbra官方已經及時對高版本的zimbra打了補丁,所以最新版只要及時更新補丁就可以預防(詳情請見Zimbra官網)。

漏洞復現

復現環境
  • Zimbra 8.5.0
  • ubuntu 14.04(172.16.123.134)(受害者服務器)
  • ubuntu 18.04 (172.16.123.1)(攻擊者服務器)

此處特別強調Zimbra只能安裝在特定版本的linux發行版上,與ubuntu適配最好,且zimbra8.5不支持ubuntu14以上的發行版

環境搭建

Zimbra的環境搭建比較麻煩,在此推薦幾篇有關zimbra搭建的優質博文
https://www.jianshu.com/p/722bc70ff426
幾個關鍵點就是選擇合適版本ubuntu虛擬機,主機hosts配置,dnsmasq的配置,最後,我們的環境可以不用配置ssl.

攻擊流程

如果你閱讀過原文,你應該已經知道我們需要利用xxe來讀取目標主機的localconfig.xml文件,這個文件中有一個類似超級管理員用戶的密碼,而這個超級管理員的用戶名默認就是zimbra,所以只要我們拿到這個密碼在某種意義上來說就相當於已經獲得了zimbra的最高權限。
但是事情沒有那麼簡單,Zimbra是使用token來進行權限管理的,而一個管理員的token只可能分配給一個來自7071端口的請求,而這個端口一般是不會對外開放的,所以,這就需要我們的ssrf上場了。但是這個ssrf利用也是有條件的,這個ssrf的利用點存在於源碼中的 ProxyServlet.doProxy() 函數處,源碼如下:
在這裏插入圖片描述
從上面的代碼邏輯中可以看出,只有在token是作爲parameter傳遞過來的纔會對其進行驗證,否則,如果token是從cookie傳過來的則不會進入驗證token這處邏輯,所以我們只需要得到一個合法的普通的token就行了,這個token要怎麼獲取呢?這裏又要利用到一個Zimbra的特性了。

我們只需要將一個普通的soap AuthRequest的用戶名更改爲zimbra就可以得到一個我們可以利用的token了(此處可能不夠清晰,具體看後續復現的操作)這個token雖然是合法的,但是它具有admin屬性,所以,我們要上傳shell,還需要得到真正的admin token,所以我們只需要利用剛剛的到的token發送一個admin soap AuthRequest,就可以在響應中得到真正的admin token了,接着再利用這個token來構造文件上傳的請求,就可以得到一個webshell了。

剛剛漏了一處細節,由於doProxy這個方法會從服務端發送一個請求到目標主機,爲了安全起見,Zimbra爲可訪問的目標主機設置了一個白名單,所以,我們還需要繞過這個白名單,具體方法就是修改host,因爲Zimbra默認管理員做任何事都是合法的,而他判斷是不是管理員的方式就是獲取host中的port(如果是7071就是管理員,否則不是),所以所有來自7071端口的請求都會被認爲合法(直接忽略白名單限制),所以我們只要將host更改爲axin:7071,再發送這個proxy請求就行了

復現過程

xxe獲取localconfig.xml
利用xxer.py搭建一個http以及ftp服務器,以此來接受xxe返回的數據
在這裏插入圖片描述
ext.dtd文件內容如下:
在這裏插入圖片描述
在這裏插入圖片描述
上圖中間的shell窗口就是攻擊者ftp服務器收到的localconfig.xml文件內容,我們只是對ldap_root_password感興趣,也就上圖中的kAQbqtlab.

獲取低權限token
此處有幾個細節需要注意,我之前以爲只要改一下用戶名就可以得到token,原來還是需要剛剛獲取的密碼正確才行,然後在xml文本中加入<account by="adminName">zimbra</account>,這樣就能得到token了。接下來我們就可以利用這個token來進行ssrf,進而得到一個admin token。
`在這裏插入圖片描述

ssrf得到admin token
利用剛剛得到的token,構造一下cookie,注意token的名字需要改爲ZM_ADMIN_AUTH_TOKEN,否則會報no auth token錯誤
然後Host頭需要改爲axin:7071,然後還需填入我們剛剛得到的用戶名以及密碼(zimbra–kAQbqtlab)這樣構造一個請求發送過去(請求到admin驗證的鏈接),就會服務器就會返回一個經過認證的admin token,接下來我們利用這個admin token上傳shell
在這裏插入圖片描述

getshell
由於我的虛擬機卡死,導致我從新復現了以此,所以讀者可能看到現在的ZM_ADMIN_AUTH_TOKEN與上面不一樣了。但是操作還是一樣的,直接拿着得到的admin token去請求這個upload連接,構造一個上傳webshell的惡意請求,這樣就可以直接上傳shell了。
在這裏插入圖片描述

成功得到shell:
在這裏插入圖片描述

注:我這裏之前存在一個誤區,我以爲文件上傳這個鏈接只能是7071端口才能訪問,導致我還是利用ssrf來進行文件上傳,結果就是一直報no auth token錯誤,最後仔細讀了一下tint0的博文,發現並沒有說要通過ssrf上傳文件,於是我就直接構造了上面那個鏈接,完成了shell上傳。

參考資料&總結

在復現的過程中,出現了很多問題,最大的問題其實就是zimbra這個東西太複雜了,很多東西只有翻手冊(甚至手冊都翻不到),比如代理的使用,以及soap api的使用,這兩個也是整個復現過程的關鍵,下面貼出鏈接:
代理使用:
https://wiki.zimbra.com/wiki/Zimlet_Developers_Guide:Proxy_Servlet_Setup
soap的使用(普通soap 認證以及管理員soap認證調用方式):
https://files.zimbra.com/docs/soap_api/8.0/soapapi-zimbra-doc/api-reference/index.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章