0x00 前言
平时工作中 需要编写poc
而poc 大多步骤是重复的
比如用户输入 等
因此写一套模板 直接套用即可
根据开普勒安全python教学视频学习编写
0x01 模板编写
1.1 引入库
import sys
import getopt
import requests
import threading
import time
import os
import datetime
import urllib3
from colorama import init, Fore # 修改命令行中颜色的库
#禁用https安全请求警告 以防网站https证书不合规 关闭警告
#urllib3.disable_warnings(urllib3.exceptions.InsecurePlatformWarning)
urllib3.disable_warnings()
#关闭自动恢复默认颜色
init(autoreset=False)
lock = threading.Lock() # 锁
global result_file_path # 结果文件路径
global proxies_judge # 代理是否开启的判断
loop_name = '' # 漏洞名称
1.2 help() 模块
def help():
'''
帮助文档
'''
print('''
-h --help 帮助文档
-u --url 目标url
-f --target_file 目标地址文件
-r --result_file 输出的信息文件地址(默认为result.txt)
-t --thread_num 多线程数量(默认50)
-p --proxies 是否开启代理,默认不开启,输入则开启 --一般用于burp抓包测试
eg:
python poc模板.py -u http://www.xxx.com
python poc模板.py -u http://www.xxx.com -p http://127.0.0.1:8080
python poc模板.py -f target.txt
python poc模板.py -f target.txt -r result.txt
python poc模板.py -f target.txt -r result.txt -t 100
''')
1.3 poc_head() 模块
def poc_head():
print("""
____ __ ___ ____ ____ _ _ ____ __ __ ____ ____
( _ \ / \ / __) (_ _)( __)( \/ )( _ \( ) / _\(_ _)( __)
) __/( O )( (__ )( ) _) / \/ \ ) __// (_/\/ \ )( ) _)
(__) \__/ \___) (__) (____)\_)(_/(__) \____/\_/\_/(__) (____)
author: youthbelief
漏洞名称: {}
""".format(loop_name))
1.4 检测模块exploit(url)
def exploit(url):
'''
poc函数
poc代码放在这里,这个函数的内容随便修改
可以使用接口output_to_file 将信息输出到文件中
可以使用接口output将信息显示在命令行中(当print用就行)
output需要2个参数,一个为显示的信息即msg,一个为信息的类型(int 0 1 2 3)
0 普通的信息 白色
1 攻击成功的信息 绿色
2 攻击失败的信息 黄色
3 出现错误的信息 红色
'''
global proxies_judge
proxies = {
"http":'http://127.0.0.1:8080',
"https":'http://127.0.0.1:8080'
}
head = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36 Edg/98.0.1108.50'
}
# 修改payload
payload = "/xxx?=/etc/passwd"
# 如果为post 请求 添加data 请求体
data = ''
exp = url + payload
try:
if proxies_judge:
re = requests.get(exp,verify=False,timeout=5,proxies=proxies)
else:
re = requests.get(exp,verify=False,timeout=5)
# 判断漏洞是否存在 根据实际漏洞情况 修改
if re.status_code == 200 and 'root' in re.text:
msg = "存在任意文件读取漏洞 "+exp
judge = 1
output_to_file(msg)
else:
msg = '不存在任意文件读取漏洞'+ url
judge = 2
except:
msg = 'error!目标路径无法访问'
judge = 3
output(msg,judge)
1.5 main() 模块整个poc运行流程
整个执行流程
def main():
poc_head()
global proxies_judge
global result_file_path
result_file_path = 'result.txt' #扫描结果默认保存到result.txt
target_num = 50 # 默认线程数为50
target_file_path = '' # 目标文件为空 需要手动输入
url = '' # url为空手动输入
msg = [] # 列表 用于存放 url
proxies_judge = False # 是否开启代理 默认为 否
try:
opts,args = getopt.getopt(sys.argv[1:],
'hu:f:r:t:p:',
['help','url=','target_file=','result_file=','thread_num=','proxies='])
except getopt.GetoptError as err:
print(str(err))
help()
#从opts中读取数据,o 为参数,a为参数后带的值
for o,a in opts:
if o in ['-h','--help']:
help()
elif o in ['-u','--url']:
url = a
elif o in ['-f','--target_file']:
target_file_path = a
try:
f = open(target_file_path,'r')
msg = f.read().split('\n') #read的结果为字符串 split以\n 分隔开 返回为列表
except:
output('目标文件路径错误!' , 3)
elif o in ['-r','--result_file']:
target_file_path = a
elif o in ['-t','--thread_num']:
target_num = int(a)
elif o in ['-p','--proxies']:
proxies_judge = True
# 定义i=0 i代表 检测次数 初始为0 后续用来判断所有目标是否扫描完毕
i = 0
# 如果 url的值为空 并且 len(msg) 不等于0 说明 我们输入的是-f 参数 进入 多线程循环
if url == '' and len(msg) != 0:
while(True):
# 如果运行的子线程< 最大线程数 并且 检测次数 < 目标数 说明 还没有检测完 可以创建新的线程 继续检测第i+1个目标
if threading.active_count()-1 < target_num and i < len(msg):
t = threading.Thread(target=exploit,args=(msg[i],))
t.start()
i+=1
output_msg = '第'+str(i)+'个目标开始检查,还有'+str(len(msg)-i)+'个目标待检查!'
output(output_msg)
# 如果 检测次数 ≥ 目标数 并且 运行的子线程数还不为0 说明所有目标都已经开始检测了 但是还有几个线程的目标没有检测完!
if i >= len(msg) and threading.active_count()-1 > 0:
output('正在检测最后'+str(threading.active_count()-1)+'个目标, 请稍等...')
time.sleep(5)
# 如果 检测次数 >= 目标数 并且运行的子线程数为0 说明 所有线程的检测目标任务完成 跳出死循环
if i >= len(msg) and threading.active_count()-1 == 0:
f = open(result_file_path,'r')
num = len(f.readlines())
f.close()
output('finish!共扫描'+str(len(msg))+'个网站,发现漏洞'+str(num)+'个!')
#修改结果后缀 有n个url存在漏洞 末尾就添加n 没必要的功能
#os.rename(result_file_path,result_file_path+str(num))
break
# 如果url的值补位空 并且 len(msg) 等于0 说明我们输入了 -u参数 只用扫描一次 不用进入多线程循环 直接扫描即可
elif url != '' and len(msg) == 0:
exploit(url)
1.6 output_to_file(msg) 模块
输出到文件的功能
def output_to_file(msg):
'''
输出到文件
'''
global result_file_path
f = open(result_file_path,'a')
f.write(msg+'\n')
f.close()
1.7 output(msg,judge=0) 模块
exlpoit() 中使用该方法
输出到命令行定义的方法
根据 judge 值判断 该输出什么颜色 默认为0 普通信息
def output(msg,judge=0):
'''
输出到命令行
在多线程的情况下,输出可能会混了,这里加了个锁来保证输出结果的稳定,但会略微影响扫描效率
如果不想要锁,追求极致的速率(mac下不加锁也不会乱 原因目前未知)
请删除
lock.acquire()
try:
finally:
lock.release()
4行代码
'''
lock.acquire()
try:
now_time = datetime.datetime.now().strftime('%H:%M:%S')
now_time = Fore.LIGHTCYAN_EX + '['+now_time+'] ' + Fore.RESET
if judge == 0:
print(now_time + msg )
elif judge == 1: #输出成功信息
print(now_time + Fore.LIGHTGREEN_EX + '[+]' + msg + Fore.RESET)
elif judge == 2 : #输出失败信息
print(now_time + Fore.LIGHTYELLOW_EX + '[-]' + msg + Fore.RESET)
elif judge == 3 : #输出错误信息
print(now_time + Fore.LIGHTRED_EX + '[-]' + msg + Fore.RESET)
finally:
lock.release()
0x02 完整代码
# -*- coding: utf-8 -*
# *python3*
# *author : youthbelief
# 漏洞类型:
# 漏洞编号
# poc作者
# 影响应用
# 影响版本
# 漏洞类型
# 漏洞概述:
# fofa查询:
import sys
import getopt
import requests
import threading
import time
import os
import datetime
import urllib3
from colorama import init, Fore # 修改命令行中颜色的库
#禁用https安全请求警告 以防网站https证书不合规 关闭警告
#urllib3.disable_warnings(urllib3.exceptions.InsecurePlatformWarning)
urllib3.disable_warnings()
#关闭自动恢复默认颜色
init(autoreset=False)
lock = threading.Lock() # 锁
global result_file_path # 结果文件路径
global proxies_judge # 代理是否开启的判断
loop_name = '' # 漏洞名称
def help():
'''
帮助文档
'''
print('''
-h --help 帮助文档
-u --url 目标url
-f --target_file 目标地址文件
-r --result_file 输出的信息文件地址(默认为result.txt)
-t --thread_num 多线程数量(默认50)
-p --proxies 是否开启代理,默认不开启,输入则开启 --一般用于burp抓包测试
eg:
python poc模板.py -u http://www.xxx.com
python poc模板.py -u http://www.xxx.com -p http://127.0.0.1:8080
python poc模板.py -f target.txt
python poc模板.py -f target.txt -r result.txt
python poc模板.py -f target.txt -r result.txt -t 100
''')
def poc_head():
print("""
____ __ ___ ____ ____ _ _ ____ __ __ ____ ____
( _ \ / \ / __) (_ _)( __)( \/ )( _ \( ) / _\(_ _)( __)
) __/( O )( (__ )( ) _) / \/ \ ) __// (_/\/ \ )( ) _)
(__) \__/ \___) (__) (____)\_)(_/(__) \____/\_/\_/(__) (____)
author: youthbelief
漏洞名称: {}
""".format(loop_name))
def exploit(url):
'''
poc函数
poc代码放在这里,这个函数的内容随便修改
可以使用接口output_to_file 将信息输出到文件中
可以使用接口output将信息显示在命令行中(当print用就行)
output需要2个参数,一个为显示的信息即msg,一个为信息的类型(int 0 1 2 3)
0 普通的信息 白色
1 攻击成功的信息 绿色
2 攻击失败的信息 黄色
3 出现错误的信息 红色
'''
global proxies_judge
proxies = {
"http":'http://127.0.0.1:8080',
"https":'http://127.0.0.1:8080'
}
head = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36 Edg/98.0.1108.50'
}
# 修改payload
payload = "/xxx?=/etc/passwd"
# 如果为post 请求 添加data 请求体
data = ''
exp = url + payload
try:
if proxies_judge:
re = requests.get(exp,verify=False,timeout=5,proxies=proxies)
else:
re = requests.get(exp,verify=False,timeout=5)
# 判断漏洞是否存在 根据实际漏洞情况 修改
if re.status_code == 200 and 'root' in re.text:
msg = "存在任意文件读取漏洞 "+exp
judge = 1
output_to_file(msg)
else:
msg = '不存在任意文件读取漏洞'+ url
judge = 2
except:
msg = 'error!目标路径无法访问'
judge = 3
output(msg,judge)
def output_to_file(msg):
'''
输出到文件
'''
global result_file_path
f = open(result_file_path,'a')
f.write(msg+'\n')
f.close()
def output(msg,judge=0):
'''
输出到命令行
在多线程的情况下,输出可能会混了,这里加了个锁来保证输出结果的稳定,但会略微影响扫描效率
如果不想要锁,追求极致的速率(mac下不加锁也不会乱 原因目前未知)
请删除
lock.acquire()
try:
finally:
lock.release()
4行代码
'''
lock.acquire()
try:
now_time = datetime.datetime.now().strftime('%H:%M:%S')
now_time = Fore.LIGHTCYAN_EX + '['+now_time+'] ' + Fore.RESET
if judge == 0:
print(now_time + msg )
elif judge == 1: #输出成功信息
print(now_time + Fore.LIGHTGREEN_EX + '[+]' + msg + Fore.RESET)
elif judge == 2 : #输出失败信息
print(now_time + Fore.LIGHTYELLOW_EX + '[-]' + msg + Fore.RESET)
elif judge == 3 : #输出错误信息
print(now_time + Fore.LIGHTRED_EX + '[-]' + msg + Fore.RESET)
finally:
lock.release()
def main():
poc_head()
global proxies_judge
global result_file_path
result_file_path = 'result.txt' #扫描结果默认保存到result.txt
target_num = 50 # 默认线程数为50
target_file_path = '' # 目标文件为空 需要手动输入
url = '' # url为空手动输入
msg = [] # 列表 用于存放 url
proxies_judge = False # 是否开启代理 默认为 否
try:
opts,args = getopt.getopt(sys.argv[1:],
'hu:f:r:t:p:',
['help','url=','target_file=','result_file=','thread_num=','proxies='])
except getopt.GetoptError as err:
print(str(err))
help()
#从opts中读取数据,o 为参数,a为参数后带的值
for o,a in opts:
if o in ['-h','--help']:
help()
elif o in ['-u','--url']:
url = a
elif o in ['-f','--target_file']:
target_file_path = a
try:
f = open(target_file_path,'r')
msg = f.read().split('\n') #read的结果为字符串 split以\n 分隔开 返回为列表
except:
output('目标文件路径错误!' , 3)
elif o in ['-r','--result_file']:
target_file_path = a
elif o in ['-t','--thread_num']:
target_num = int(a)
elif o in ['-p','--proxies']:
proxies_judge = True
# 定义i=0 i代表 检测次数 初始为0 后续用来判断所有目标是否扫描完毕
i = 0
# 如果 url的值为空 并且 len(msg) 不等于0 说明 我们输入的是-f 参数 进入 多线程循环
if url == '' and len(msg) != 0:
while(True):
# 如果运行的子线程< 最大线程数 并且 检测次数 < 目标数 说明 还没有检测完 可以创建新的线程 继续检测第i+1个目标
if threading.active_count()-1 < target_num and i < len(msg):
t = threading.Thread(target=exploit,args=(msg[i],))
t.start()
i+=1
output_msg = '第'+str(i)+'个目标开始检查,还有'+str(len(msg)-i)+'个目标待检查!'
output(output_msg)
# 如果 检测次数 ≥ 目标数 并且 运行的子线程数还不为0 说明所有目标都已经开始检测了 但是还有几个线程的目标没有检测完!
if i >= len(msg) and threading.active_count()-1 > 0:
output('正在检测最后'+str(threading.active_count()-1)+'个目标, 请稍等...')
time.sleep(5)
# 如果 检测次数 >= 目标数 并且运行的子线程数为0 说明 所有线程的检测目标任务完成 跳出死循环
if i >= len(msg) and threading.active_count()-1 == 0:
f = open(result_file_path,'r')
num = len(f.readlines())
f.close()
output('finish!共扫描'+str(len(msg))+'个网站,发现漏洞'+str(num)+'个!')
#修改结果后缀 有n个url存在漏洞 末尾就添加n 没必要的功能
#os.rename(result_file_path,result_file_path+str(num))
break
# 如果url的值补位空 并且 len(msg) 等于0 说明我们输入了 -u参数 只用扫描一次 不用进入多线程循环 直接扫描即可
elif url != '' and len(msg) == 0:
exploit(url)
if __name__ == '__main__':
main()
0x03 运行演示