[javaweb]strut2-001漏洞分析
Strut2-001
https://github.com/Aur0ra-m/JavaWeb/blob/main/Strut2/strut2-001.md
漏洞描述
框架解析JSP页面标签时会对用户输入的Value值获取,在获取对应的Value值中递归解析%{、}
造成了二次解析,最终触发表达式注入漏洞,执行任意代码
影响版本
2.0.1 ~ 2.0.8
漏洞分析
环境搭建了好久。。。最后看到一篇https://xz.aliyun.com/t/2672#toc-2,才成功,不知道错误在哪儿。最后发现是和tomcat的版本也有关系
建议:环境搭建能搭好即可,不要太深究为什么。不要偏离主线--分析漏洞
Strut2中的数据流向:请求-》filterStack-》action-》view-》Client
-
首先直接定位到ParametersInterceptor中的doFilter方法
-
ParametersInterceptor先是建立了一个值栈,并通过setParameters进行储值操作(后门要用,直接从值栈中查)
-
经过一系列的拦截器处理后,数据会成功进入实际业务 Action 。程序会根据 Action 处理的结果,选择对应的 JSP 视图进行展示,并对视图中的 Struts2 标签进行处理。如下图,在本例中 Action 处理用户登录失败时会返回 error 。
然后开始对index,jsp中的struts2标签进行处理
也就是所谓的标签渲染,把其中的标签通过文件解析替换为既定目标语法
/** TextParseUtil#translateVariables()分析 */ public static Object translateVariables(char open, String expression, ValueStack stack, Class asType, ParsedValueEvaluator evaluator) { // deal with the "pure" expressions first! //expression = expression.trim(); Object result = expression; while (true) { int start = expression.indexOf(open + "{"); int length = expression.length(); int x = start + 2; int end; char c; int count = 1; while (start != -1 && x < length && count != 0) { c = expression.charAt(x++); if (c == '{') { count++; } else if (c == '}') { count--; } } end = x - 1; if ((start != -1) && (end != -1) && (count == 0)) { String var = expression.substring(start + 2, end); Object o = stack.findValue(var, asType); if (evaluator != null) { o = evaluator.evaluate(o); } String left = expression.substring(0, start); String right = expression.substring(end + 1); if (o != null) { if (TextUtils.stringSet(left)) { result = left + o; } else { result = o; } if (TextUtils.stringSet(right)) { result = result + right; } expression = left + o + right; } else { // the variable doesn't exist, so don't display anything result = left + right; expression = left + right; } } else { break; } } return XWorkConverter.getInstance().convertValue(stack.getContext(), result, asType); }
上面的函数大概的流程就是先找到%{param},然后提取中间的内容,把%{}左右两边的字符串先截断出来分为left,right,对param进行findValue,找到了就把left+value(param)+right进行重新拼接,如果没有就直接将左右两边进行拼接。这是一个正常的标签处理逻辑(学过编译原理的应该很熟悉)。
漏洞点:如果传进去的参数值为%{1+1},到了29L: findValue(var, asType),那么此时就会再次进行递归解析(感觉和ssti类似),从而触发Expression Inject
漏洞利用
payload:
%{(new java.lang.ProcessBuilder(new java.lang.String[]{"calc.exe"})).start()}
将calc.exe替换成其他即可进行任意命令执行
漏洞修复
漏洞形成的原因无非就是递归解析字符串造成的。所以只要不让它递归解析即可。
最后官方给出了上面的修复,也就是限制默认的递归次数,而不是禁止递归。猜想官方应该是为了避免部分情况下还是需要进行递归解析留下了余地吧。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】