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 | tomcat高版本会严格按照 RFC 3986规范进行访问解析,而 RFC 3986规范定义了Url中只允许包含英文字母 a-zA-Z、数字0-9、-_.~ 4个特殊字符以及所有保留字符(RFC3986中指定了以下字符为保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ]) |
漏洞分析
根据官方概述,问题出现在ParameterInterceptors.java。
此时我们在ParametersInterceptor拦截器入口方法进行断点doIntercept()
在getValueStack
之前,执行了一些初始化操作,将xwork.MethodAccessor.denyMethodExecution
设置为true
。为了能够调用方法,需要在poc中的第一部分将denyMethodExecution
设置为false
,之后才能任意代码执行。
跟入setParameters(action, stack, parameters);
此部分开始通过迭代器取出一个个传入的参数,并进行处理。
跟入acceptableName
发现acceptableName
方法判断参数是否含有非法字符,可以发现非法字符中包含 #
号,所以我们的 payload
需要将 #
号编码成 \u0023
。通过校验后,会调用 setValue
方法将值添加进值栈
跟入setValue
方法,该方法中调用了Ognl.setValue()
Ognl.setValue()
方法中会调用 compile
方法对字符串进行解析,在解析字符串时,程序会对 \u
字符进行解码。
又会回到 Ognl.setValue()
,表达式的解析执行
对参数名特殊字符过滤不完善,通过\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
的源码
官方通过增加禁止静态方法调用 allowStaticMethodAcces
、类方法执行 MethodAccessor.den yMethodExecution
等安全配置来进行修复,我们可以利用 OGNL
表达式来进行操作更改值,从而进行一个绕过。
修复
使用了更加严格的正则 [a-zA-Z0-9\\.\\]\\[\\(\\)_'\\s]+
来校验参数名的合法性。