Struts2 S2-037漏洞预警

漏洞描述
Apache Struts2在使用REST插件的情况下,攻击者使用REST调用恶意表达式可以远程执行代码。该漏洞编号为CVE-2016-4438,定名S2-037。该漏洞和S2-033漏洞触发流程基本一致,都是在ActionMapping中methodName带入到OGNL表达式中执行,从而导致任意代码执行。

影响范围
Struts 2.3.20 – Struts 2.3.28.1
所有安装REST插件的Struts应用

漏洞原理
在5月12日安恒报告的CVE-2016-3087(S2-033)中,若Struts2应用安装REST插件,且开启DMI(Dynamic Method Invocation)动态方法调用,攻击者可以注入恶意表达式造成远程代码执行。官方补丁公告(https://cwiki.apache.org/confluence/display/WW/S2-033)中描述写道:
Remote Code Execution can be performed when using REST Plugin with ! operator when Dynamic Method Invocation is enabled.
S2-033影响范围为:
Struts 2.3.20 – Struts Struts 2.3.28 (except 2.3.20.3 and 2.3.24.3)
然而在官方修补该漏洞过程中,只是在DefaultActionMapper.java文件中加入了对method成员的值进行OGNL表达式过滤
https://github.com/apache/struts/blob/095960b5691d33f127000794b3e79638cf384652/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java
3701
然而在该漏洞触发代码中,还有另一个入口,于是导致了S2-037的发生
Struts2的rest插件在处理类似http://127.0.0.1:8080/chaitin/action-name/1/rr的URLs时,会查找名字以rr的方法调用,即actionname中的public String rr()会被调用
3702

该处methodName没有做过滤校验,直接放入了mapping中,造成了代码执行

验证PoC
验证检测:
http://127.0.0.1:8080/chaitin/memeda/rr/(%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS%29%3f(%23wr%3d%23context%5b%23parameters.obj%5b0%5d%5d.getWriter(),%23wr.println(%23parameters.content[0]),%23wr.flush(),%23wr.close()):xx.toString.json?&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=vulntestbyrr
response中回显vulntestbyrr即存在该漏洞

修复方案
加入cleanupActionName方法进行过滤
如同文中所述的S2-033中的修复方案,对method成员进行过滤,在mapping.setMethod(fullName.substring(lastSlashPos + 1));
该行加入cleanupActionName方法进行过滤即为 mapping.setMethod(cleanupActionName()fullName.substring(lastSlashPos + 1)));

根据官方漏洞公告和建议及时修复
官方公告https://cwiki.apache.org/confluence/display/WW/S2-037中的建议升级到2.3.29.
Upgrade to Apache Struts version 2.3.29.

作者 长亭科技