调试S2-033到S2-037分析体会

0x00 背景

最近出了两个Struts漏洞,S2-032S2-037。 都是官方插件REST出了问题,zone里面讨论也很热烈。
我只代表个人观点和理解,如果理解有误,请批评指正。顺便聊聊里面的技术。

首先,看两个漏洞的描述:

S2-033(CVE-2016-3087):

Remote Code Execution can be performed when using REST Plugin with ! operator when Dynamic Method Invocation is enabled.

S2-037:

Remote Code Execution can be performed when using REST Plugin.
It is possible to pass a malicious expression which can be used to execute arbitrary code on server side when using the REST Plugin.

可以看到区别就是S2-037没有提到要开启动态方法调用(Dynamic Method Invocation)。

这就有点意思了,看看源码或许能发现好玩的地方。

0x01 漏洞原理

首先简单看看这个REST插件是干啥的,那就查看下官方文档。翻译下,给个直观的感受:

REST插件,会使用RESTful风格处理URL请求,大概的映射规则如下:

其他的就不赘述了。

关键在Struts2运行机制中,会去加载各个插件中struts-plugin.xml配置文件。
下面是一部分struts2-rest-plugin插件struts-plugin.xml内容:

上面两个配置,便成功将处理URL请求和action调用的代理类,设置成了插件中的类。

S2-033

于是就来看看org.apache.struts2.rest.RestActionMapper,这个处理URL请求的类。和S2-032,S2-016出问题一样的处理类,请参考Struts2方法调用远程代码执行漏洞(CVE-2016-3081)分析

于是,我们看到了这样的一段处理URL的代码:

标记的很清楚,handleDynamicMethodInvocation函数用来处理name!method形式的URL。通过S2-032,我们知道,倘若没有对method进行过滤的话,便会造成OGNL命令执行了。接着跟进看看:

果真,没有经过任何处理。于是有了S2-033漏洞:当动态方法调用开启后,可以通过name!evilcodeMethod的方式进行攻击,POC下面再讲。 evilcodeMethod便是我们攻击的代码了。

S2-037

闲的无聊,可以看看剩下的处理URL代码,发现了这样一段代码:

注释写的很清楚:

好的开发人员,注释清晰明了。
于是,发现了这里竟然也存在了一个methodName,这里是否也没过滤?答案在上述代码中,依然没有过滤。

并且这里并不需要开启动态方法调用。我猜这就是S2-037了,乌云社区里面的POC也映证了我的想法。

0x02 POC及其测试

POC请看http://zone.wooyun.org/content/27865,写的蛮好的。我单纯聊聊里面有趣的技术。

由于这两个漏洞的根本就是S2-032,自然POC就和S2-032一样了,于是就有人误以为是S2-032的POC了。

1. S2-033漏洞POC

我记得在乌云社区中s2-033三种POC+命令执行绕过,就已经出现了S2-037的漏洞点,只是没有注意到并不需要启动动态调用方法

我们就跟着官方说的,开启动态方法调用来看一下。如何利用!来进行攻击。

测试环境:

官方的下载struts-all包,在apps目录下有一个struts2-rest-showcase.war文件,可以直接用来测试。

为了调试POC,我复制里面的文件,新建了一个项目进行测试。

重现S2-033,我改了两处:

  • 增加动态方法调用。

  • 去掉验证输入是否为空。

由于无法正常传id,所以在验证完整性的时候,便终止了。于是删掉做测试。

得到的POC如下:

2. 绕过后缀检测

对于S2-032漏洞的POC来说,程序解析的后缀为.String,这里需要伪造成.json(或xhtml,xml等)绕过这个限制。关键代码如下:

于是就有了与S2-032 POC不一样的多余.xhtml后缀。

3. S2-037

区别只是利用点不一样,却不需要开启动态方法调用:

这个利用点,明显舒服多了,POC一模一样~~而且直接使用官方样例,即可测试:

在官方样例程序,直接使用POC攻击:

0x03 巧妙的绕过OGNL

以上POC有限制,在最新的2.38.1和2.3.20.1等版本中,无法让OGNL执行多条语句。

在我写这个的时候,乌云发出了最新的一篇分析文章

通过三目运算符这个方式绕过,赞叹~ 真心值得好好学习,有空一定跟踪源码再看看原理~urldecode看看清楚:

so great~ 相当于执行了两条语句。

依次类推,可以做很多事情~ 再次感叹一下~~

0x04 最后说一下

新的绕过方式真心值得学习,好好看源码,多多思考,能得到好的回报~~

0x05 参考

Struts2 S033与最新S037详细分析
Struts2方法调用远程代码执行漏洞(CVE-2016-3081)分析