Struts2-003、005漏洞分析

Struts2-003

漏洞概要

可参考官方安全公告:https://cwiki.apache.org/confluence/display/WW/S2-003

POC:

1
login.action?('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003dfalse')(bla)(bla)&('\u0023myret\[email protected]@getRuntime().exec(\'calc\')')(bla)(bla)

s2-003漏洞的payload用到了特殊字符,这里使用低版本tomcat6来测试。

1
2
3
4
tomcat高版本会严格按照 RFC 3986规范进行访问解析,而 RFC 3986规范定义了Url中只允许包含英文字母 a-zA-Z、数字0-9、-_.~ 4个特殊字符以及所有保留字符(RFC3986中指定了以下字符为保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ])

在高版本的tomcat,如果url中要使用下列字符,需要进行url编码,否则会返回400状态码。
^[]{}\|"<>`

漏洞分析

根据官方概述,问题出现在ParameterInterceptors.java。

此时我们在ParametersInterceptor拦截器入口方法进行断点doIntercept()

getValueStack之前,执行了一些初始化操作,将xwork.MethodAccessor.denyMethodExecution设置为true。为了能够调用方法,需要在poc中的第一部分将denyMethodExecution设置为false,之后才能任意代码执行。

image-20201222161256364

跟入setParameters(action, stack, parameters);此部分开始通过迭代器取出一个个传入的参数,并进行处理。

image-20201222154340316

跟入acceptableName发现acceptableName 方法判断参数是否含有非法字符,可以发现非法字符中包含 #号,所以我们的 payload需要将 # 号编码成 \u0023 。通过校验后,会调用 setValue 方法将值添加进值栈

image-20201222155111292

image-20201222155058451

image-20201222162610882

跟入setValue 方法,该方法中调用了Ognl.setValue()

image-20201222154519290

image-20201222160456612

Ognl.setValue() 方法中会调用 compile 方法对字符串进行解析,在解析字符串时,程序会对 \u 字符进行解码。

image-20201222160221068

image-20201222174507709

image-20201222174704079

image-20201222181149389

image-20201222182008083

又会回到 Ognl.setValue() ,表达式的解析执行

image-20201222164908265

image-20201222165844689

对参数名特殊字符过滤不完善,通过\u0023(16进制的#)、八进制的\43,绕过正则表达式,从而执行了OGNL表达式.

Struts2-005

漏洞概要

可参考官方安全公告:https://cwiki.apache.org/confluence/display/WW/S2-005

1
S2-005漏洞的起源源于S2-003(受影响版本: 低于Struts 2.0.12),struts2会将http的每个参数名解析为OGNL语句执行(可理解为java代码)。OGNL表达式通过#来访问struts的对象,struts框架通过过滤#字符防止安全问题,然而通过unicode编码(u0023)或8进制(43)即绕过了安全限制,对于S2-003漏洞,官方通过增加安全配置(禁止静态方法调用和类方法执行等)来修补,但是安全配置被绕过再次导致了漏洞,攻击者可以利用OGNL表达式将这些选项打开,S2-003的修补方案把自己上了一个锁,但是把锁钥匙给插在了锁头上。—— 《白帽子讲Web安全》

POC:

1
login.action?('\u0023_memberAccess[\'allowStaticMethodAccess\']')(meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew%20java.lang.Boolean("false")))&(asdf)(('\u0023rt.exit(1)')(\u0023rt\[email protected]@getRuntime()))=1

漏洞分析

S2-005 是对 S2-003 修复的绕过,对比一下 ParametersInterceptor 的源码

image-20201224161108681

image-20201224161151927

官方通过增加禁止静态方法调用 allowStaticMethodAcces 、类方法执行 MethodAccessor.den yMethodExecution 等安全配置来进行修复,我们可以利用 OGNL 表达式来进行操作更改值,从而进行一个绕过。

image-20201224162439935

修复

使用了更加严格的正则 [a-zA-Z0-9\\.\\]\\[\\(\\)_'\\s]+ 来校验参数名的合法性。

image-20201224184426800

参考

https://xz.aliyun.com/t/7966

https://xz.aliyun.com/t/2323

https://mp.weixin.qq.com/s/xaVxdYPRIhlxiFLy9WhUHA

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

-本文结束感谢您的阅读-