作者:廖新喜
綜述
2017年9月5日,Apache Struts 發布最新的安全公告,Apache Struts 2.5.x 和 2.3.x 的 REST 插件存在遠程代碼執行的高危漏洞,漏洞編號為 CVE-2017-9805(S2-052)。漏洞的成因是由于使用 XStreamHandler 反序列化 XStream 實例的時候沒有任何類型過濾導致遠程代碼執行。
相關鏈接如下: https://cwiki.apache.org/confluence/display/WW/S2-052
影響版本: Struts 2.1.2 - Struts 2.3.33, Struts 2.5 - Struts 2.5.12
規避方案: 立即升級到Struts 2.5.13 or Struts 2.3.34
技術分析
根據官方的描述信息來看,是 REST 插件使用到 XStreamHandler 處理 xml 數據的時候,由于未對 xml 數據做任何過濾,在進行反序列將 xml 數據轉換成 Object 時導致的 RCE。
0x01 環境搭建
從官方地址下載所有源碼包,找到其中的 struts2-rest-showcase.war 直接部署到 tomcat 就行,當然我更喜歡手動編譯,直接通過 Maven 編譯即可。具體的部署過程這里就不詳細描述,不過有點是需要注意的,由于 javax.imageio 的依賴關系,我們的環境的 jdk 版本需要是 jdk8 以上,jdk8 某些低版本也是不行的,本文作者的版本是 jdk8_102,后續的一些驗證都是在這個版本上做的。
0x02 補丁分析
環境搭建好了之后,首先我們來看下 rest 插件的相關配置

從這個文件中就可以看出 XStreamHanler 就是Content-Type:xml的默認處理句柄,而且可以看出xml是默認支持格式,這也就是說存在rest插件就會存在XStream的反序列化漏洞。
接著看看官方的修復方案,補丁地址:https://github.com/apache/struts/commit/19494718865f2fb7da5ea363de3822f87fbda264
在官方的修復方案中,主要就是將 xml 中的數據白名單化,把 Collection 和 Map,一些基礎類,時間類放在白名單中,這樣就能阻止 XStream 反序列化的過程中帶入一些有害類。

0x03 POC的生成
目前公開的 Poc 是基于 javax.imageio 的,這是能直接本地執行命令,但是 marshelsec 提供了11個 XStream 反序列化庫,其中大部分都是基于 JNDI,具體包含:CommonsConfiguration, Rome, CommonsBeanutils, ServiceLoader, ImageIO, BindingEnumeration, LazySearchEnumeration, SpringAbstractBeanFactoryPointcutAdvisor, SpringPartiallyComparableAdvisorHolder, Resin, XBean, 從外部請求類完成反序列化。
0x04 漏洞驗證及簡單分析
下圖是一個簡單的驗證分析圖,從Poc中可以看出,請求是PUT,請求的url后綴帶xml,請求的Content-Type為delicious/bookmark+xml,請求的xml的前綴是 <set>.

接著我們看下觸發的執行調用棧:
在 XStreamHanler.toObject 調用了 XStream 的 fromXml,從而進入反序列化流程。

0x05 官方臨時緩解措施不起作用
官方給出的緩解措施 <constant name="struts.action.extension" value="xhtml,,,json" />,從字面意思也能看出來,這個是針對 action 的后綴的,也就是說如果后綴不帶 xml 也就可以繞過。下面給出測試用例,從我們的 poc 中也可以看出,POST 請求不帶 xml 的后綴直接忽視這個緩解措施。所以說 Struts 的官方也不怎么復制,沒測試過的東西就直接放出來。XStream 只跟 Content-Type 有關,如果 Content-Type 中含有 xml,則會交給 XStream 處理,所以 poc 該怎么使還怎么使,并且目前最大的問題就是國內的解決都是使用的這個無效的官方解決方案,下面看下我們的驗證:

從圖上可以看出,我們已經去除了 xml 的支持,下面來看看 Payload 的執行效果:

成功彈出計算器,這也就驗證了我們的想法。同時通過兩個不同poc的比較,我們也能發現一些端倪,Content-Type支持xml的幾種格式,POST 請求,PUT 請求,GET 請求甚至是自定義請求都是能觸發漏洞,我們可以將poc中 <map><entry>換成 <set> 也能觸發漏洞。同時由于 XStream 本身的 Poc 多達十一種,做好安全防御確實比較艱難。
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/384/