Struts2 REST插件在使用xstreamhandler处理反序列化XML时没有进行任何过滤,从而导致远程执行代码,攻击者可以利用该漏洞构造恶意的XML内容获取服务器权限。

漏洞分析

首先看一下struts-plugin.xml配置文件,当Content-Type为xml时会调用XStreamHandler类进行处理

lVq36g.png

在struts-plugin.xml配置文件中可见,当Content-Type为xml时会调用XStreamHandler类进行处理

lVqJmj.png

此外,从上图还可以看出xml是struts2请求中后缀的默认支持格式

当请求报文中Content-Type为”application/xml”时,程序会调用XStreamHandler.toObject

lVqPfK.png

toObject方法中将会调用XStream.fromXML对传入的xml的内容进行反序列化。在这个过程中,XStream没有对Reader做任何过滤处理

我们通过调试代码来跟踪一下实际的流程

首先我们构造如下数据包以触发漏洞

lVbbWT.png

构造如上图请求数据,将请求中的Content-Type设置为application/xml

当请求进入struts2的Content-Type拦截器即ContentTypeInterceptor时,程序会根据请求中Content-Type类型寻找对应的handler,并调用handler进行反序列化操作,如下图

lVqklD.png

ContentTypeInterceptor具体的执行流程如下:

1、程序通过getHandlerForRequest方法会判断提交的请求类型并使用对应的handler

lVqZmd.png

lVqMff.png

由上图可见,此时Content-Type为application/xml形式的请求对应的handler为XStreamHandler

2、通过getContentLength方法获取提交的数据包长度,如果长度大于0则就获取其输入流并将其生成一个InputStreamReader对象赋值给reader,操作见下图红框

lVbjOJ.png

3、调用对应handler的toObject方法将reader数据流进行xml反序列化

lVqST1.png

通过上图可见,在这里对应的handler为XStreamHandler

跟进XStreamHandler类的toObject方法

lVqUkq.png

lVqY0s.png

XStreamHandler类中toObject方法调用 XStream.fromXML对xml的内容进行反序列化

fromXML方法见下图

lVqt7n.png

XStreamHandler并未对传入的Reader做过滤处理,因此导致反序列化漏洞的产生

lVqukt.png

针对官方缓解措施的分析

官方给出的缓解措施是修改struts-plugin.xml 中”struts.action.extension”属性,将xml字段从其中删除

struts.action.extension指定需要Struts2处理的请求后缀,该属性的默认值是action,即 所有匹配*.action的请求都由Struts2处理。如 果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开

原始的struts-plugin.xml 配置如下

lVq8XQ.png

通过上图可知:struts-plugin.xml 中的配置表明,后缀为*.xhtml,*.xml,*.json后缀的请求都有Struts2处理

官方给出的缓解措施

<constant name=”struts.action.extension” value=”xhtml,,,json” />

仅仅将配置中的xml去掉。也就是说,当出现*.xml后缀的请求,Struts2不再处理

但是反观我们的poc

lVqat0.png

并没有使用xml作为后缀

程序是否使用XStreamHandler进行反序列化操作,仅仅是通过content-Type类型是否为application/xml来判断,因此缓解措施无效