漏洞描述
Apache Dubbo是一款高性能Java RPC框架,核心功能是方便面向接口的遠程過程調用,集群容錯和負載均衡,以及服務自動注冊與發現。
Apache Dubbo支持多種協議,官方默認為 Dubbo 協議。當用戶選擇http協議進行通信時,Apache Dubbo 將接受來自消費者遠程調用的POST請求並執行一個反序列化的操作。由於此步驟沒有任何安全校驗,因此可以造成反序列化執行任意代碼。
漏洞影響范圍:
- 2.7.0 <= Apache Dubbo <= 2.7.4
- 2.6.0 <= Apache Dubbo <= 2.6.7
- Apache Dubbo = 2.5.x
環境搭建
復現環境:win10 + jdk1.8 + idea(搭建dubbo) + zookeeper 3.4.10
ZooKeeper是一個分布式的,開放源碼的分布式應用程序協調服務,主要是用來解決分布式應用中經常遇到的一些數據管理問題。
首先先下載zookeeper的壓縮包:https://archive.apache.org/dist/zookeeper/zookeeper-3.4.10/zookeeper-3.4.10.tar.gz
然后在解壓后的根目錄下新建兩個文件夾:data和logs,后面配置要用到。
接着修改 conf目錄下的zoo_sample.cfg為zoo.cfg,
並添加如下內容,分別為剛剛新建的data和logs目錄路徑

雙擊bin目錄下的 zkServer.cmd,啟動,zookeeper會監聽2181端口

zookeeper配置好后,開始搭建dubbo,這里以官方的domo為例:https://github.com/apache/dubbo-samples/tree/master/java/dubbo-samples-http
下載后修改dubbo-samples-http里面的pom.xml
先修改版本為2.7.3,然后添加依賴:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>

然后導入idea,maven下載依賴構建項目即可。(如果下載時間特別長,可以考慮更換源,方法參考:https://www.cnblogs.com/zaqzzz/p/12443794.html)
最后啟動dubbo\samples\http\HttpProvider服務,出現dubbo service started 就說明搭建完成了。

復現分析
首先要先通過反序列化工具ysoserial生成payload,保存到calc.ser文件
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections4 "calc" > calc.ser
瀏覽器訪問http://192.168.1.101:8080/org.apache.dubbo.samples.http.api.DemoService 並burp抓包該請求,首先先修改為post類型,接着在post的內容里導入我們剛剛生成的payload,不要直接復制,burp右鍵Paste from file添加payload

發包,成功彈出了計算器。

下面簡單分析下該漏洞,從idea的報錯調用棧可以看出,javax.servlet.http.HttpServlet.service應該就是入口

查看javax.servlet.http.HttpServlet.service,在有處理request請求的地方加個斷點,如下

重新開啟調試模式,burp再次發送攻擊請求,來到斷點處

跟入來到DispatcherServlet的service方法,通過請求中的端口去獲取服務信息,如果沒有則返回404 Service not found

下面繼續跟入handle方法,由於我們傳輸的協議是http,所以就進到了HttpProtocol類中對應的handle方法。

然后先判斷請求類型是不是為post,如果不是的話就直接返回500。
確定請求類型為post后,根據請求的內容生成HttpInvokerServiceExporter對象,最后再調用其handleRequest方法,跟入查看

這里發現是通過readRemoteInvocation 來處理我們的request請求,繼續跟入

這里返回了readRemoteInvocation的結果,繼續跟入

可以看到,這里先是獲取了我們request請求的數據流,接着傳入到了doReadRemoteInvocation方法,跟入查看

可以看到反序列化入口了,這里直接調用了Readobject,整個攻擊請求的處理流程基本清晰了,這個漏洞其實並不復雜,修復的話可以直接升級到2.7.5以上,或者關閉http協議,其他的思路的話還可以考慮用jsonrpc的處理,而不是通過httpinvoker,這樣的話就沒辦法處理我們的java序列化字節流從而拋出異常。
reference:
http://www.lmxspace.com/2020/02/16/Apache-Dubbo反序列化漏洞(CVE-2019-17564)
