对表单参数使用validator验证时,如果遇到类型错误,参数值会先压入参数栈,之后会取出并被二次ognl解析
Struts 2.0.0 - 2.2.3
validation机制参考:
https://www.cnblogs.com/BrowserSnake/p/3745445.html
官网下载对应lib,需要这几个jar:

写一个最简单的action

再写一个表单提交到action

然后创建action,如果输入成功就会显示index内容,输入验证不过则会继续输入,验证未通过的result是input

然后在action的同目录下创建validation,名称是action类名-validation.xml,这里验证表单提交的参数id必须是int型,且范围是[1,10],如果验证不通过返回message的内容,跳转到result input标签所指定的页面,否则返回success

以下是验证:
'+(111*222)+'

验证存在后,表单发送:
'+(#_memberAccess.allowStaticMethodAccess=true ,#context["xwork.MethodAccessor.denyMethodExecution"]=false,@java.lang.Runtime@getRuntime().exec('calc'))+'

漏洞是由于参数类型转换错误为入口触发的,在xwork中有对于类型转换错误的拦截器ConversionErrorInterceptor

在其intercept方法加断点,首先POST的参数已经在参数栈了

取出错误的参数,放到空map,放入之前先进行了getOverrideExpr()

输入的参数用单引号包裹,因此payload有单引号是利用字符串拼接截断了,然后构建了正常ognl表达式

fakie这个map放到了context

处理完拦截器后之后,数据会填入前台页面,这里在渲染的时候,通过ComponentTagSupport.doEndTag()方法会解析参数,同S2-001

首先解析出变量名

然后解析变量值

获取值的类型是String,然后把参数名包裹成OGNL表达式,通过OGNL解析来获取值以供渲染用

ognl解析都是复用util的代码

来到tryFindValue,expr会变成参数值,然后调用getValue

最终调用Ognl.getValue()解析单引号截断的表达式,完成注入

由于类型转换错误以及自定义validator错误,全部都渲染到模板上了,开发者这一步是为了提供一个重新输入的功能,返回到result的name是input

'+(xxx)+'由于S2自带了commons-io,方便了执行任意命令
'+(#_memberAccess.allowStaticMethodAccess=true ,#context["xwork.MethodAccessor.denyMethodExecution"]=false,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('whoami').getInputStream()))+'
https://cwiki.apache.org/confluence/display/WW/S2-007
欢迎关注我的CSDN博客 :@Ho1aAs
版权属于:Ho1aAs
本文链接:https://blog.csdn.net/Xxy605/article/details/126505065
版权声明:本文为原创,转载时须注明出处及本声明