正在阅读:

Struts2 S2-052漏洞分析

5,867

漏洞概述:

漏洞编号:CVE-2017-9805(S2-052)

影响版本:Struts 2.5 - Struts 2.5.12

漏洞概述:问题出现在struts2-rest-plugin插件XStreamHandler处理器中的toObject()方法,其中未对传入的值进行任何限制,在使用XStream反序列化转换成对象时,导致任意代码执行漏洞。

0x00 调试环境搭建

使用官方的rest-sample即可,下载2.5.12版本的源码

https://github.com/apache/struts/archive/STRUTS_2_5_12.zip

然后将apps下面的rest-showcase源码脱下来。

Eclipse中新建一个maven工程,web.xml,pom.xml和struts.xml如下:

pom.xml

<!-- struts2依赖包 -->  
<dependency>  
<groupId>org.apache.struts</groupId>  
<artifactId>struts2-core</artifactId>  
<version>2.5.12</version>  
</dependency>  
<!-- struts restful 依赖包 -->  
<dependency>  
<groupId>org.apache.struts</groupId>  
<artifactId>struts2-convention-plugin</artifactId>  
<version>2.5.12</version>  
</dependency>  
<dependency>  
<groupId>org.apache.struts</groupId>  
<artifactId>struts2-rest-plugin</artifactId>  
<version>2.5.12</version>  
</dependency>  

struts.xml(src/main/resources/下)

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE struts PUBLIC  
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"  
"http://struts.apache.org/dtds/struts-2.5.dtd">  
<struts>  
<!-- Overwrite Convention -->  
<constant name="struts.convention.action.suffix" value="Controller"/>  
<constant name="struts.convention.action.mapAllMatches" value="true"/>  
<constant name="struts.convention.default.parent.package" value="rest-default"/>  
<constant name="struts.convention.package.locators" value="action"/>  
<constant name="struts.convention.result.path" value="/WEB-INF/"/>  
</struts>  

其他的action文件、jsp文件复制过来到maven工程的对应目录即可,右键启动项目,然后浏览器可以访问到:

http://127.0.0.1:8080/struts2-052/orders,说明调试环境搭建成功。

0x01 漏洞分析

根据该漏洞发现者文章https://lgtm.com/blog/apache_struts_CVE-2017-9805所述,是一个叫ContentHandler的东西有问题。

在2.5.12源码中搜索这个字符串:

strutss2052-1

在struts-plugin.xml配置了很多的bean,这些bean按照content-type进行分类,并唯一指定一个具体的Handler。

这些Handler都实现了ContentTypeHandler接口。

从API DOC上描述

Handles transferring content to and from objects for a specific content type

来看,这个ContentTypeHandler实际上是按照Content-type的不同,将请求的数据丢给指定的子类进行处理,具体是怎么处理的呢,以XStreamHandler为例:

strutss2052-2

这里实际上就是把XML和java对象之间进行转化,比较专业的词汇叫“marshal“和”“unmarshal”。

从以往的例子看,这种情况导致的命令执行也不是一次两次了,json转换库如fastjson,jackson都有过漏洞,这次换成了Struts2里的XML的对象转换。

其实就是XStreamHandler的toObject方法中触发了漏洞,我们就先在这行代码下断点,执行poc之后,会发现断点生效了。

我们来看看调用函数流程信息:

strutss2052-3

在Restful模式下,对Action的路由处理是使用Rest系列的代码,这里是ContentTypeInterceptor类调用的XStreamHandler方法。我们来看看上层代码中的intercept方法:

strutss2052-4

首先是从HttpServletRequest里判断ContentType,可以很清晰的看到,通过ContentType将request的字节流分发给对应的Handler进行处理。当ContentType为application/xml的时候,

很自然的就分发给了XStreamHandler这个类来处理,这个类没有进行任何校验,直接进行了转换。我们可以用marsshalsec工具来生成payload。

(1)下载源码https://github.com/mbechler/marshalsec

(2)maven编译 mvn clean package -DskipTests

(3)去target目录下找到jar文件,执行:

java -cp marshalsec-0.0.1-SNAPSHOT-all.jar marshalsec.XStream ImageIO "calc" > 1.txt  

然后将这段XML用POST发给struts2-rest,当然,ContentType要设置为xml的,然后就可以触发了。当命令中有空格时,提交多个节点即可。

0x02 后话

关于如何从XML到命令执行的过程,实际上是Moritz Bechler大神的一个paper,

https://github.com/mbechler/marshalsec/blob/master/marshalsec.pdf

这个paper随着marshalsec工具发布。

这里只分析Struts2的漏洞原因,关于XML->RCE过程,大家可以仔细阅读这个paper进行深入了解。

原文地址:

http://blog.csdn.net/u011721501/article/details/77867633

参考网址:

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

https://bbs.ichunqiu.com/thread-26789-1-1.html

目前有:1条访客评论

  1. lz
    2018-03-23 19:55

    能 学会渗透。看懂漏洞。吃不完用不完呀

留下脚印,证明你来过。

*

*

流汗坏笑撇嘴大兵流泪发呆抠鼻吓到偷笑得意呲牙亲亲疑问调皮可爱白眼难过愤怒惊讶鼓掌