├── module ├── __init__.py ├── config.ini ├── is_ip.py ├── is_unique.py ├── but_upload.py ├── bugcloud_upload.py ├── get_icp.py ├── thor_upload.py ├── but_bypass.py ├── thor_bypass.py ├── is_logic.py ├── get_domain.py ├── thor_submit.py ├── bugcloud_submit.py ├── get_shoot.py └── but_submit.py ├── .idea ├── .gitignore ├── vcs.xml └── 补天自动化提交漏洞提交.iml ├── temp ├── icp.png ├── site.png ├── thor.png ├── vul.png └── domain.png ├── images ├── img.png ├── img_1.png ├── img_2.png ├── img_3.png └── img_4.png ├── url.txt ├── requirements.txt ├── LICENSE ├── main.py └── readme.md /module/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # 默认忽略的文件 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /temp/icp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/york-cmd/CharVulFlow/HEAD/temp/icp.png -------------------------------------------------------------------------------- /temp/site.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/york-cmd/CharVulFlow/HEAD/temp/site.png -------------------------------------------------------------------------------- /temp/thor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/york-cmd/CharVulFlow/HEAD/temp/thor.png -------------------------------------------------------------------------------- /temp/vul.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/york-cmd/CharVulFlow/HEAD/temp/vul.png -------------------------------------------------------------------------------- /images/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/york-cmd/CharVulFlow/HEAD/images/img.png -------------------------------------------------------------------------------- /images/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/york-cmd/CharVulFlow/HEAD/images/img_1.png -------------------------------------------------------------------------------- /images/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/york-cmd/CharVulFlow/HEAD/images/img_2.png -------------------------------------------------------------------------------- /images/img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/york-cmd/CharVulFlow/HEAD/images/img_3.png -------------------------------------------------------------------------------- /images/img_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/york-cmd/CharVulFlow/HEAD/images/img_4.png -------------------------------------------------------------------------------- /temp/domain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/york-cmd/CharVulFlow/HEAD/temp/domain.png -------------------------------------------------------------------------------- /module/config.ini: -------------------------------------------------------------------------------- 1 | [config] 2 | chinaz = 3 | appkey = 4 | 5 | [but] 6 | cookie = 7 | 8 | [thor] 9 | cookie = 10 | 11 | [bugcloud] 12 | cookie = -------------------------------------------------------------------------------- /url.txt: -------------------------------------------------------------------------------- 1 | http://w9akqhsnukputwh7.xinlan.web.zjcbo.net:3000/jshERP-boot/user/getAllList;.ico 2 | https://erp.211.daxue.cloud:443/jshERP-boot/user/getAllList;.ico 3 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/补天自动化提交漏洞提交.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /module/is_ip.py: -------------------------------------------------------------------------------- 1 | import socket 2 | from urllib.parse import urlparse 3 | 4 | 5 | def is_ip(url): 6 | url = urlparse(url).netloc 7 | url = url.split(":")[0] 8 | # print(url) 9 | try: 10 | ip = socket.gethostbyname(url) 11 | if ip == url: 12 | return True 13 | else: 14 | return False 15 | except: 16 | return False 17 | 18 | # print(is_ip("http://www.baidu.com:8080/123")) # domain 19 | -------------------------------------------------------------------------------- /module/is_unique.py: -------------------------------------------------------------------------------- 1 | from urllib.parse import urlparse 2 | from module.is_ip import is_ip 3 | 4 | 5 | def is_unique(path): 6 | unique_domains = set() 7 | new_is = [] 8 | 9 | with open(path, 'r') as file: 10 | for i in file: 11 | url = i.strip() 12 | netloc = urlparse(url).netloc 13 | if is_ip(i): 14 | domain = netloc.split(':')[0] 15 | # print(domain) 16 | else: 17 | domain = '.'.join(netloc.split('.')[-2:]) 18 | if domain not in unique_domains: 19 | unique_domains.add(domain) 20 | new_is.append(url) 21 | 22 | with open(path, 'w') as file: 23 | for i in new_is: 24 | file.write(i + '\n') 25 | print(f"Complete deduplication! Start {len(new_is)} tasks") 26 | -------------------------------------------------------------------------------- /module/but_upload.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | from time import sleep 4 | 5 | requests.packages.urllib3.disable_warnings() 6 | # proxies = {'http': 'http://127.0.0.1:8080', 'https': 'https://127.0.0.1:8080'} 7 | proxies = {} 8 | headers = { 9 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.183'} 10 | 11 | 12 | def but_upload(pash): 13 | files = {"upfile": ("a.png", open(pash, "rb"), "image/jpeg")} 14 | try: 15 | rsp = requests.post("https://www.butian.net/Public/ueditor/php/controller.php?action=uploadimage", files=files, 16 | verify=False, timeout=30, proxies=proxies) 17 | # print(rsp.text) 18 | except requests.exceptions.RequestException: 19 | print("上传图片超时") 20 | sleep(5) 21 | return but_upload(pash) 22 | data = json.loads(rsp.text) 23 | data = data["url"] 24 | # print(data) 25 | return data 26 | 27 | # but_upload(pash="D:/360/CharVulFlow/temp/site.png") 28 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | attrs==23.1.0 2 | brotlipy==0.7.0 3 | certifi==2022.12.7 4 | cffi==1.15.1 5 | charset-normalizer==2.0.4 6 | colorama==0.4.6 7 | coloredlogs==15.0.1 8 | cryptography==39.0.1 9 | ddddocr==1.4.7 10 | exceptiongroup==1.1.2 11 | filelock==3.9.0 12 | flatbuffers==23.5.26 13 | h11==0.14.0 14 | humanfriendly==10.0 15 | idna==3.4 16 | importlib-metadata==6.7.0 17 | mpmath==1.3.0 18 | numpy==1.21.6 19 | onnxruntime==1.14.1 20 | opencv-python-headless==4.8.0.74 21 | outcome==1.2.0 22 | packaging==23.1 23 | Pillow==9.5.0 24 | pip==22.3.1 25 | protobuf==4.23.4 26 | pycparser==2.21 27 | pyOpenSSL==23.0.0 28 | pyreadline==2.1 29 | PySocks==1.7.1 30 | requests==2.28.1 31 | requests-file==1.5.1 32 | selenium==4.11.2 33 | setuptools==65.6.3 34 | six==1.16.0 35 | sniffio==1.3.0 36 | sortedcontainers==2.4.0 37 | sympy==1.10.1 38 | tldextract==3.2.0 39 | tqdm==4.65.0 40 | trio==0.22.2 41 | trio-websocket==0.10.3 42 | typing_extensions==4.7.1 43 | urllib3==1.26.8 44 | wheel==0.38.4 45 | win-inet-pton==1.1.0 46 | wincertstore==0.2 47 | wsproto==1.2.0 48 | zipp==3.15.0 49 | -------------------------------------------------------------------------------- /module/bugcloud_upload.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | from time import sleep 4 | 5 | requests.packages.urllib3.disable_warnings() 6 | # proxies = {'http': 'http://127.0.0.1:8080', 'https': 'https://127.0.0.1:8080'} 7 | proxies = {} 8 | headers = { 9 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.183', 10 | } 11 | # print(proxies) 12 | 13 | def bugcloud_upload(path): 14 | files = {"qh_img": ("a.png", open(path, "rb"), "image/jpeg")} 15 | try: 16 | res = requests.post("https://src.360.net/api/frontend/fpublic/imgupload", files=files, 17 | verify=False, timeout=5, proxies=proxies) 18 | # print(res.text) 19 | except Exception as e: 20 | print(e) 21 | # sleep(5) 22 | return bugcloud_upload(path) 23 | data = json.loads(res.text) 24 | data = data["result"]["img_url"] 25 | # print(data) 26 | return data 27 | 28 | # bugcloud_upload(path="D:/360/CharVulFlow/temp/site.png") 29 | -------------------------------------------------------------------------------- /module/get_icp.py: -------------------------------------------------------------------------------- 1 | import json 2 | from urllib.parse import urlparse 3 | 4 | import requests 5 | import configparser 6 | import ast 7 | import os 8 | 9 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 10 | config = configparser.ConfigParser() 11 | config.read(os.path.join(BASE_DIR, 'config.ini')) 12 | 13 | 14 | def get_icp(url): 15 | if url.startswith("http"): 16 | url = urlparse(url).netloc 17 | else: 18 | url = f"http://{url}" 19 | key = config.get('config', 'chinaz') 20 | url = f"https://apidatav2.chinaz.com/single/icp?key={key}&domain={url}" 21 | res = requests.get(url=url) 22 | # print(res.text) 23 | data = json.loads(res.text) 24 | if data["Result"] == None: 25 | return [] 26 | elif data["Result"]["CompanyType"] == "个人": 27 | return [] 28 | elif data["StateCode"] == 1: 29 | return data["Result"]["CompanyName"] 30 | elif data["StateCode"] == 10022: 31 | print("[WARN] chinaz调用次数不足") 32 | else: 33 | print(data["Reason"]) 34 | return [] 35 | 36 | # print(get_icp(url="mingshang.cc")) 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 imHuFei! 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /module/thor_upload.py: -------------------------------------------------------------------------------- 1 | import configparser 2 | import json 3 | import os 4 | import requests 5 | 6 | requests.packages.urllib3.disable_warnings() 7 | BASE_DIR1 = os.path.dirname(os.path.abspath(__file__)) 8 | BASE_DIR2 = os.path.dirname(BASE_DIR1) 9 | config = configparser.ConfigParser() 10 | config.read(os.path.join(BASE_DIR1, 'config.ini')) 11 | cookie = config.get('thor', 'cookie') 12 | 13 | head = { 14 | 'Host': 'bug.bountyteam.com', 15 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.183', 16 | 'Authorization': cookie, 17 | 'Cookie': f"JSESSIONID={cookie}", 18 | 'Acceptlanguage': 'zh', 19 | 'Referer': 'https://bug.bountyteam.com/commitSrcBug'} 20 | 21 | 22 | def thor_upload(path): 23 | file = {"file": ("a.png", open(path, "rb"), "image/jpeg")} 24 | try: 25 | url = "https://bug.bountyteam.com/api/uploadImg" 26 | res = requests.post(url=url, files=file, headers=head, verify=False, timeout=30) 27 | # print(res.text) 28 | except Exception as e: 29 | print(e) 30 | data = json.loads(res.text) 31 | data = data["data"]["url"] 32 | # print(data) 33 | return data 34 | 35 | # thor_upload() 36 | -------------------------------------------------------------------------------- /module/but_bypass.py: -------------------------------------------------------------------------------- 1 | import json 2 | from time import sleep 3 | import configparser 4 | import requests 5 | import json 6 | import os 7 | 8 | requests.packages.urllib3.disable_warnings() 9 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 10 | config = configparser.ConfigParser() 11 | config.read(os.path.join(BASE_DIR, 'config.ini')) 12 | appkey = config.get('config', 'appkey') 13 | 14 | def but_bypass(): 15 | try: 16 | res1 = requests.get("https://www.butian.net/Loo/startCaptcha", verify=False) 17 | except: 18 | return but_bypass() 19 | zidian = json.loads(res1.text) 20 | date = {'appkey': f'{appkey}', 'gt': '4fd5d5dbea6b9365f94fc525fee2cf20', 21 | 'challenge': zidian["challenge"], 'referer': 'https://www.butian.net/Loo/submit'} 22 | res2 = requests.post(url="http://api.rrocr.com/api/recognize.html", data=date) 23 | # print(res2.text) 24 | if "识别成功" in res2.text: 25 | zidian = json.loads(res2.text) 26 | return zidian["data"]["challenge"], zidian["data"]["validate"] 27 | pass 28 | elif "识别失败" in res2.text: 29 | return but_bypass() 30 | elif "积分不足" in res2.text: 31 | print("验证识别账户积分不足") 32 | return [] 33 | else: 34 | sleep(3) 35 | return but_bypass() 36 | 37 | # print(but_bypass()) 38 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from module.is_logic import is_but 2 | from module.is_logic import is_thor 3 | from module.is_logic import is_bugcloud 4 | from module.is_unique import is_unique 5 | from tqdm import tqdm 6 | import time 7 | 8 | banner = '''\033[32m[INFO] 目前支持补天[is_but] 雷神[is_thor] 360众包[is_bugcloud]; 9 | _________ .__ ____ ____ .__ ___________.__ 10 | \_ ___ \| |__ _____ ______\ \ / /_ __| | \_ _____/| | ______ _ __ 11 | / \ \/| | \\__ \\_ __ \ Y / | \ | | __) | | / _ \ \/ \/ / 12 | \ \___| Y \/ __ \| | \/\ /| | / |__| \ | |_( <_> ) / 13 | \______ /___| (____ /__| \___/ |____/|____/\___ / |____/\____/ \/\_/ 14 | \/ \/ \/ \/ 15 | [INFO] 建议脚本Pycharm运行,方便修改代码; 16 | [INFO] 建议脚本_VMware运行,不会干扰工作;\033[0m''' 17 | 18 | path = "url.txt" # 存在漏洞url文件 19 | is_unique(path) # 去重url.txt 20 | print(banner) 21 | with open(path, 'r', encoding="utf-8") as f: 22 | urls = f.readlines() 23 | for i in tqdm(urls): 24 | i = i.strip() 25 | try: 26 | is_but(i) # 补天提交逻辑流 27 | # is_thor(i) # 雷神提交逻辑流 28 | # is_bugcloud(i) # 众包提交逻辑流 29 | except: 30 | pass 31 | time.sleep(15) 32 | -------------------------------------------------------------------------------- /module/thor_bypass.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import configparser 3 | import os 4 | import ddddocr 5 | import requests 6 | import json 7 | 8 | BASE_DIR1 = os.path.dirname(os.path.abspath(__file__)) 9 | BASE_DIR2 = os.path.dirname(BASE_DIR1) 10 | # print(BASE_DIR2) 11 | config = configparser.ConfigParser() 12 | config.read(os.path.join(BASE_DIR1, 'config.ini')) 13 | cookie = config.get('thor', 'cookie') 14 | head = { 15 | 'Host': 'bug.bountyteam.com', 16 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.183', 17 | 'Authorization': cookie, 18 | 'Cookie': f'{cookie}', 19 | 'Acceptlanguage': 'zh', 20 | 'Referer': 'https://bug.bountyteam.com/commitSrcBug'} 21 | 22 | 23 | # 获取雷神提交验证图形 24 | def get_img(): 25 | url1 = "https://bug.bountyteam.com/api/pictureVerifyCode" 26 | data = {"type": 1} 27 | res1 = requests.post(url=url1, headers=head, json=data, verify=False) 28 | # print(res.text) 29 | data = json.loads(res1.text) 30 | img = data["data"]["photo"].split(',')[1] 31 | img = base64.b64decode(img) 32 | file = open(os.path.join(BASE_DIR2, 'temp', 'thor.png'), "wb") 33 | file.write(img) 34 | 35 | 36 | # 识别图像 37 | def get_ocr(): 38 | ocr = ddddocr.DdddOcr() 39 | with open(os.path.join(BASE_DIR2, 'temp', 'thor.png'), 'rb') as f: 40 | img_bytes = f.read() 41 | res = ocr.classification(img_bytes).upper() 42 | if len(res) == 4: 43 | # print(res) 44 | return res 45 | else: 46 | get_ocr() 47 | 48 | 49 | def thor_bypass(): 50 | get_img() 51 | return get_ocr() 52 | 53 | # print(thor_bypass()) 54 | -------------------------------------------------------------------------------- /module/is_logic.py: -------------------------------------------------------------------------------- 1 | from module.get_shoot import shoot_isip 2 | from module.get_shoot import shoot_noip 3 | from module.get_domain import getsite_all 4 | from module.thor_submit import thor_submit 5 | from module.but_submit import but_submit 6 | from module.bugcloud_submit import bugcloud_submit 7 | from module.is_ip import is_ip 8 | from urllib.parse import urlparse 9 | 10 | 11 | def is_thor(i): 12 | if is_ip(i): 13 | url = urlparse(i).netloc 14 | ip = url.split(":")[0] 15 | domain = getsite_all(ip) 16 | if domain == "": 17 | print("查无域名") 18 | pass 19 | else: 20 | # print(i, domain) 21 | shoot_isip(i, domain) 22 | thor_submit(i, domain) 23 | else: 24 | # print(i) 25 | shoot_noip(i) 26 | thor_submit(i, "") 27 | 28 | 29 | def is_but(i): 30 | if is_ip(i): 31 | url = urlparse(i).netloc 32 | ip = url.split(":")[0] 33 | domain = getsite_all(ip) 34 | if domain == "": 35 | print("查无域名") 36 | pass 37 | else: 38 | # print(i, domain) 39 | shoot_isip(i, domain) 40 | but_submit(i, domain) 41 | else: 42 | # print(i) 43 | shoot_noip(i) 44 | but_submit(i, "") 45 | 46 | 47 | def is_bugcloud(i): 48 | if is_ip(i): 49 | url = urlparse(i).netloc 50 | ip = url.split(":")[0] 51 | domain = getsite_all(ip) 52 | if domain == "": 53 | print("查无域名") 54 | pass 55 | else: 56 | # print(i, domain) 57 | shoot_isip(i, domain) 58 | bugcloud_submit(i, domain) 59 | else: 60 | # print(i) 61 | shoot_noip(i) 62 | bugcloud_submit(i, "") 63 | -------------------------------------------------------------------------------- /module/get_domain.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | import re 4 | 5 | proxies = {} 6 | # proxies = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'} 7 | requests.packages.urllib3.disable_warnings() 8 | 9 | 10 | def getsite_ip138(url): 11 | ip138_head = { 12 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.188"} 13 | ip138_path = f"https://site.ip138.com/{url}/" 14 | try: 15 | ip138_res = requests.get(url=ip138_path, headers=ip138_head, timeout=10, verify=False, proxies=proxies) 16 | if '暂无结果' not in ip138_res.text: 17 | site = re.findall(r"""""", ip138_res.text) 18 | # print(f"ip138查询{site}") 19 | return site 20 | else: 21 | return [] 22 | except Exception as e: 23 | print(f"ip138{e}") 24 | return [] 25 | pass 26 | 27 | 28 | def getsite_webscan(url): 29 | webscan_head = {"Referer": "https://dns.aizhan.com/", 30 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.188"} 31 | webscan_path = f"http://api.webscan.cc/?action=query&ip={url}/" 32 | try: 33 | # proxies = random.choice(proxies_list) 34 | webscan_res = requests.get(url=webscan_path, headers=webscan_head, timeout=10, verify=False, proxies=proxies) 35 | domains_reg = r"(?Phttps?://)?(?P[^:/\s]+\.[a-zA-Z]{2,})" 36 | webscan_res = json.loads(webscan_res.text) 37 | sites = [] 38 | for item in webscan_res: 39 | match = re.search(domains_reg, item["domain"]) 40 | if match: 41 | domain = match.group("domain") 42 | sites.append(domain) 43 | return sites 44 | else: 45 | return [] 46 | # print(sites) 47 | except Exception as e: 48 | print(f"webscan{e}") 49 | return [] 50 | pass 51 | 52 | 53 | def getsite_all(url): 54 | ip138 = getsite_ip138(url) 55 | # webscan = getsite_webscan(url) 56 | # sites = ip138 + webscan 57 | sites = ip138[0] 58 | # print(sites) 59 | return sites 60 | 61 | # print(getsite_all("112.27.219.239")) 62 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | **CharVulFlow_V1.0.1【补天 | 雷神 | 360众包】** 2 | 3 | ``` 4 | _________ .__ ____ ____ .__ ___________.__ 5 | \_ ___ \| |__ _____ ______\ \ / /_ __| | \_ _____/| | ______ _ __ 6 | / \ \/| | \\__ \\_ __ \ Y / | \ | | __) | | / _ \ \/ \/ / 7 | \ \___| Y \/ __ \| | \/\ /| | / |__| \ | |_( <_> ) / 8 | \______ /___| (____ /__| \___/ |____/|____/\___ / |____/\____/ \/\_/ 9 | \/ \/ \/ \/ 10 | ``` 11 |

12 | 13 | 14 | 15 |

16 | 17 | ### 0x00、项目说明 18 | 1. 需求:满足公益漏洞大批量提交需要(尤其针对零权活动),减少人工时间成本; 19 | 2. 支持漏洞类型:GET类型请求,结果可直接回显浏览器(未授权访问、信息泄露、弱口令等); 20 | 3. 支持个性化制:自定义需要截图证明,建议提前与审核商量好提交。 21 | 4. 后续计划加入:权重检测模块,满足日常不参加活动公益漏洞提交。 22 | 23 | ### 0x01、配置文件 24 | 25 | 1. 在module.get_shoot修改适合你电脑的webdrive配置,参考: 26 | - [Edge浏览器配置Selenium](https://blog.csdn.net/tk1023/article/details/109078613) 27 | - Chrome浏览器配置Selenium需修改部分代码 28 | - 第17行代码需要修改为自己的电脑用户名,否则截图浏览器出现弹窗。 29 | 30 | 31 | 2. 在module.config填写需要的cookie以及apikey: 32 | - [补天公益提交入口](https://www.butian.net/Loo/submit/); 33 | - [雷神公益提交入口](https://bug.bountyteam.com/index); 34 | - [360众包提交入口](https://src.360.net/home); 35 | - [站长之家API获取](https://my.chinaz.com/ChinazAPI/DataCenter/MyDataApi); 36 | - [滑块验证API获取](http://rrocr.com/); 37 | ``` 38 | [config] # API:站长ICP|滑动验证 39 | chinaz = eaxxxxxxxxxxxxxxxxxxxxxxxxxxx43b 40 | appkey = d2xxxxxxxxxxxxxxxxxxxxxxxxxxx52e 41 | 42 | [but] # 补天 43 | cookie = wzws_sessionid=xxxxxx; PHPSESSID=xxxxxx; __btu__=xxxxxx; __btc__=xxxxxx; __btuc__=xxxxxx 44 | 45 | [thor] # 雷神 46 | cookie = 25xxxxxx-d1b7-4277-a79d-xxxxxxxxxx35 47 | 48 | [bugcloud] # 360众包 49 | cookie = sessionID=xxxxxx; Q_UDID=xxxxxx 50 | ``` 51 | 4. 在url.txt填写能回显的所有url,选择注释main函数 **补天 is_but | 雷神 is_thor | 360众包 is_bugcloud** 选择平台运行。 52 | 53 | ### 0x02、使用效果 54 | - jshERP-boot未授权访问为例:直接访问/jshERP-boot/user/getAllList;.ico即可获取所有用户账户密码。 55 | ![img_1.png](images%2Fimg_1.png) 56 | 57 | - 程序运行截图 58 | 59 | ``` 60 | 0%| | 0/3 [00:00 0: 34 | company = get_icp(domain) 35 | else: 36 | company = get_icp(url) 37 | # 判断是否存在公司 38 | if company == []: 39 | return 40 | 41 | url1 = tldextract.extract(url) 42 | host = url1.domain + "." + url1.suffix 43 | image1 = thor_upload(os.path.join(BASE_DIR2, 'temp', 'site.png')) 44 | sleep(5) 45 | image2 = thor_upload(os.path.join(BASE_DIR2, 'temp', 'vul.png')) 46 | sleep(5) 47 | image3 = thor_upload(os.path.join(BASE_DIR2, 'temp', 'icp.png')) 48 | # print("img") 49 | if len(domain) > 0: 50 | image4 = thor_upload(os.path.join(BASE_DIR2, 'temp', 'domain.png')) 51 | whois = f''' 52 | [[§p§]]IP查询[[§/p§]][[§p§]][[§img src="{image4}"§]][[§br§]][[§/p§]] 53 | [[§p§]]ICP查询[[§/p§]][[§p§]][[§img src="{image3}"§]][[§br§]][[§/p§]]''' 54 | else: 55 | whois = f''' 56 | [[§p§]]ICP查询[[§/p§]][[§p§]][[§img src="{image3}"§]][[§br§]][[§/p§]]''' 57 | # 提交前获取验证识别 58 | code = thor_bypass() 59 | # print("bypass") 60 | data = {"companyName": company, 61 | "companyIp": ["36.134.45.156"], 62 | "companyDomainName": [host], 63 | "holeTitle": f"{company}敏感信息泄露", 64 | "industryCode": "000050", 65 | "provinceCode": "370000", 66 | "cityCode": "371500", 67 | "selfEvaluationTime": "", 68 | "selfEvaluationLevel": 2, 69 | "holeType": "信息泄露", 70 | "holeUrl": [url], 71 | "holeDetail": f''' 72 | [[§p§]]### 归属证明:[[§/p§]] 73 | {whois} 74 | [[§p§]]### 复现步骤:[[§/p§]] 75 | [[§p§]]1.网站首页[[§/p§]][[§p§]][[§img src="{image1}"§]][[§br§]][[§/p§]] 76 | [[§p§]]2.直接访问漏洞url即可发现敏感文件已下载,看浏览器右上角,打开如下[[§/p§]] 77 | [[§p§]]漏洞所在[[§/p§]][[§p§]][[§img src="{image2}"§]][[§br§]][[§/p§]] 78 | ''', 79 | "repairPropose": "鉴权过滤", 80 | "verifyCode": code, 81 | "holeDesc": "", 82 | "holeHarm": "", 83 | "userId": 1367 84 | } 85 | 86 | try: 87 | url1 = "https://bug.bountyteam.com/api/hole/add" 88 | res1 = requests.post(url=url1, headers=head, json=data, verify=False) 89 | # print(res1.text) 90 | except Exception as e: 91 | print(e) 92 | data = json.loads(res1.text) 93 | if data["code"] == 200: 94 | print(f"雷神成功提交{company}") 95 | # 验证失败 96 | elif data["code"] == 201: 97 | return thor_submit(url, domain) 98 | else: 99 | print(data["message"]) 100 | 101 | # url = "" 102 | # domain = "" 103 | # thor_submit(url, domain) 104 | -------------------------------------------------------------------------------- /module/bugcloud_submit.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from time import sleep 3 | from urllib.parse import urlparse 4 | from tldextract import tldextract 5 | from module.get_icp import get_icp 6 | from module.bugcloud_upload import bugcloud_upload 7 | 8 | import json 9 | import requests 10 | import configparser 11 | import os 12 | 13 | # proxies = {'http': 'http://127.0.0.1:8080', 'https': 'https://127.0.0.1:8080'} 14 | proxies = {} 15 | 16 | BASE_DIR1 = os.path.dirname(os.path.abspath(__file__)) 17 | BASE_DIR2 = os.path.dirname(BASE_DIR1) 18 | config = configparser.ConfigParser() 19 | config.read(os.path.join(BASE_DIR1, 'config.ini')) 20 | cookie = config.get('bugcloud', 'cookie') 21 | head = { 22 | 'Host': 'src.360.net', 23 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.183', 24 | 'Cookie': f"{cookie}", 25 | 'Acceptlanguage': 'zh', 26 | 'Referer': 'https://src.360.net/submit-bug'} 27 | 28 | def bugcloud_csrf(): 29 | url2 = "https://src.360.net//api/frontend/user/userdetail" 30 | try: 31 | res2 = requests.post(url=url2, headers=head, verify=False) 32 | except Exception as e: 33 | print(e) 34 | data = json.loads(res2.text) 35 | data = data["result"]["csrf_token"] 36 | return data 37 | 38 | # print(bugcloud_csrf()) 39 | 40 | def bugcloud_submit(url, domain): 41 | # 判断是否存在domain 42 | if len(domain) > 0: 43 | company = get_icp(domain) 44 | else: 45 | company = get_icp(url) 46 | # print(company) 47 | # 判断是否存在公司 48 | if company == []: 49 | return 50 | 51 | url1 = tldextract.extract(url) 52 | host = url1.domain + "." + url1.suffix 53 | image1 = bugcloud_upload(os.path.join(BASE_DIR2, 'temp', 'site.png')) 54 | sleep(5) 55 | image2 = bugcloud_upload(os.path.join(BASE_DIR2, 'temp', 'vul.png')) 56 | sleep(5) 57 | image3 = bugcloud_upload(os.path.join(BASE_DIR2, 'temp', 'icp.png')) 58 | # print("img") 59 | if len(domain) > 0: 60 | image4 = bugcloud_upload(os.path.join(BASE_DIR2, 'temp', 'domain.png')) 61 | whois = f''' 62 |

IP查询:

归属查询:

''' 63 | else: 64 | whois = f''' 65 |

归属查询:

''' 66 | # print(whois) 67 | # 提交前获取验证识别 68 | csrf = bugcloud_csrf() 69 | # print("csrf") 70 | data = {"business_name": f"{company}所属网站", 71 | "title": f"{company}敏感信息泄露", 72 | "bug_type": "1", 73 | "bug_level": "5", 74 | "desc_v": f"{company}敏感信息泄露", 75 | "rec_step": f'''

归属证明:{whois}

1.网站首页:

2.漏洞截图:

''', 76 | "repair_plan": "

鉴权过滤,限制接口访问,及时更新

", 77 | "annex": {}, 78 | "web_name": f"{company}", 79 | "web_ip": f"{domain}", 80 | "province": "北京市", 81 | "city": "北京市", 82 | "area": "市辖区", 83 | "bug_category_main": "1", 84 | "bug_category": "45", 85 | "bug_url": f"{url}", 86 | "csrf_token": f"{csrf}", 87 | "is_use_common_bug": "5", 88 | "component_name": "", 89 | "first_industry": "1", 90 | "second_industry": "122", 91 | # "bug_id": "7lYPXe4aG/k=" 92 | } 93 | # print(data) 94 | try: 95 | url1 = "https://src.360.net/api/frontend/hacker/bugmanage/submitbug" 96 | res1 = requests.post(url=url1, headers=head, json=data, verify=False, proxies=proxies) 97 | # print(res1.text) 98 | except Exception as e: 99 | print(e) 100 | data = json.loads(res1.text) 101 | if data["code"] == 200: 102 | print(f"360众包成功提交{company}") 103 | # 验证失败 104 | elif data["code"] == 201: 105 | return bugcloud_submit(url, domain) 106 | else: 107 | print(data["msg"]) 108 | 109 | # url = "http://1.14.8.252:8088/808gps/MobileAction_downLoad.action?path=/WEB-INF/classes/config/jdbc.properties" 110 | # domain = "mingshang.cc" 111 | # bugcloud_submit(url, domain) 112 | -------------------------------------------------------------------------------- /module/get_shoot.py: -------------------------------------------------------------------------------- 1 | from urllib.parse import urlparse 2 | from selenium import webdriver 3 | from selenium.webdriver.common.by import By 4 | from time import sleep 5 | from PIL import ImageGrab 6 | import os 7 | 8 | BASE_DIR1 = os.path.dirname(os.path.abspath(__file__)) 9 | BASE_DIR2 = os.path.dirname(BASE_DIR1) 10 | 11 | 12 | def shoot_noip(url): 13 | bbox = (0, 0, 1920, 1080) 14 | options = webdriver.EdgeOptions() 15 | options.add_experimental_option('excludeSwitches', ['enable-automation']) 16 | options.add_argument('--ignore-certificate-errors') 17 | options.add_argument('--user-data-dir=C:\\Users\\hushuang1\\AppData\\Local\\Microsoft\\Edge\\User Data\\Default') 18 | driver = webdriver.Edge(options=options) 19 | # driver.get(r'https://www.baidu.com/') 20 | driver.maximize_window() 21 | 22 | result = urlparse(url) 23 | # **********截图icp备案********** 24 | try: 25 | url1 = "https://icp.chinaz.com/" + result.netloc 26 | driver.get(url1) 27 | except Exception as e: 28 | driver.quit() 29 | return "shibai" 30 | sleep(3) 31 | im = ImageGrab.grab(bbox) 32 | im.save(os.path.join(BASE_DIR2, 'temp', 'icp.png')) 33 | 34 | # **********截图主页********** 35 | try: 36 | url2 = result.scheme + "://" + result.netloc 37 | driver.get(url2) 38 | except Exception as e: 39 | driver.quit() 40 | return "shibai" 41 | sleep(3) 42 | im = ImageGrab.grab(bbox) 43 | im.save(os.path.join(BASE_DIR2, 'temp', 'site.png')) 44 | 45 | # **********截图漏洞********** 46 | try: 47 | url3 = url 48 | driver.get(url3) 49 | except Exception as e: 50 | driver.quit() 51 | return "shibai" 52 | sleep(3) 53 | im = ImageGrab.grab(bbox) 54 | im.save(os.path.join(BASE_DIR2, 'temp', 'vul.png')) 55 | 56 | sleep(2) 57 | driver.quit() 58 | 59 | 60 | # shoot_noip("https://www.mingshang.cc:443/808gps/MobileAction_downLoad.action?path=/WEB-INF/classes/config/jdbc.properties") 61 | 62 | def shoot_isip(url, domain): 63 | bbox = (0, 0, 1920, 1080) 64 | options = webdriver.EdgeOptions() 65 | options.add_experimental_option('excludeSwitches', ['enable-automation']) 66 | options.add_argument('--ignore-certificate-errors') 67 | options.add_argument('--user-data-dir=C:\\Users\\hushuang1\\AppData\\Local\\Microsoft\\Edge\\User Data\\Default') 68 | driver = webdriver.Edge(options=options) 69 | # driver.get(r'https://www.baidu.com/') 70 | driver.maximize_window() 71 | 72 | # **********截图icp备案********** 73 | if url.startswith("http"): 74 | domain = domain 75 | else: 76 | domain = f"http://{domain}" 77 | try: 78 | result = urlparse(domain) 79 | # print(result) 80 | driver.get("https://icp.chinaz.com/" + result.netloc + result.path) 81 | except Exception as e: 82 | driver.quit() 83 | return "shibai" 84 | sleep(3) 85 | im = ImageGrab.grab(bbox) 86 | im.save(os.path.join(BASE_DIR2, 'temp', 'icp.png')) 87 | result = urlparse(url) 88 | # print(result) 89 | 90 | # **********截图ip反查********** 91 | try: 92 | url1 = result.netloc 93 | url1 = url1.split(":")[0] 94 | driver.get("https://site.ip138.com/" + url1) 95 | except Exception as e: 96 | sleep(3) 97 | sleep(3) 98 | im = ImageGrab.grab(bbox) 99 | im.save(os.path.join(BASE_DIR2, 'temp', 'domain.png')) 100 | 101 | # **********截图主页********** 102 | try: 103 | # print(result) 104 | url2 = result.scheme + "://" + result.netloc 105 | driver.get(url2) 106 | except Exception as e: 107 | driver.quit() 108 | # print(f"{e}site") 109 | return "shibai" 110 | sleep(3) 111 | im = ImageGrab.grab(bbox) 112 | im.save(os.path.join(BASE_DIR2, 'temp', 'site.png')) 113 | 114 | # **********截图漏洞********** 115 | try: 116 | url3 = url 117 | driver.get(url3) 118 | except Exception as e: 119 | driver.quit() 120 | return "shibai" 121 | sleep(3) 122 | im = ImageGrab.grab(bbox) 123 | im.save(os.path.join(BASE_DIR2, 'temp', 'vul.png')) 124 | 125 | sleep(2) 126 | driver.quit() 127 | driver.close() 128 | 129 | # shoot_isip("http://1.14.8.252:8088/808gps/MobileAction_downLoad.action?path=/WEB-INF/classes/config/jdbc.properties", "xjrjyy.cn") 130 | -------------------------------------------------------------------------------- /module/but_submit.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from time import sleep 3 | from urllib.parse import urlparse 4 | from tldextract import tldextract 5 | from module.get_icp import get_icp 6 | from module.but_bypass import but_bypass 7 | from module.but_upload import but_upload 8 | 9 | import random 10 | import json 11 | import requests 12 | import configparser 13 | import os 14 | 15 | requests.packages.urllib3.disable_warnings() 16 | BASE_DIR1 = os.path.dirname(os.path.abspath(__file__)) 17 | BASE_DIR2 = os.path.dirname(BASE_DIR1) 18 | config = configparser.ConfigParser() 19 | config.read(os.path.join(BASE_DIR1, 'config.ini')) 20 | cookie = config.get('but', 'cookie') 21 | 22 | session = requests.session() 23 | headers = { 24 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.183', 25 | 'Cookie': f'{cookie}'} 26 | 27 | # proxies = {'http': 'http://127.0.0.1:8080', 'https': 'https://127.0.0.1:8080'} 28 | proxies = {} 29 | 30 | 31 | def but_submit(url, domain): 32 | if len(domain) > 0: 33 | company = get_icp(domain) 34 | else: 35 | company = get_icp(url) 36 | # print(company) 37 | if company == []: 38 | return 39 | # 获取主页截图上传 40 | url1 = tldextract.extract(url) 41 | host = url1.domain + "." + url1.suffix 42 | 43 | image1 = but_upload(os.path.join(BASE_DIR2, 'temp', 'site.png')) 44 | image1 = image1.replace("\/", "/") 45 | sleep(5) 46 | image2 = but_upload(os.path.join(BASE_DIR2, 'temp', 'vul.png')) 47 | image2 = image2.replace("\/", "/") 48 | sleep(5) 49 | image3 = but_upload(os.path.join(BASE_DIR2, 'temp', 'icp.png')) 50 | image3 = image3.replace("\/", "/") 51 | 52 | if len(domain) > 0: 53 | image4 = but_upload(os.path.join(BASE_DIR2, 'temp', 'domain.png')) 54 | image4 = image4.replace("\/", "/") 55 | whois = f''' 56 | index.png 57 | index.png''' 58 | else: 59 | whois = f''' 60 | index.png''' 61 | # 滑块识别 62 | challenge, validate = but_bypass() 63 | if (challenge == "shibai"): 64 | return 65 | detail = f"""

归属证明截图:{whois} 66 | 访问首页截图:index.png

67 |

漏洞所在url:{url}

68 |


69 |

漏洞验证步骤:

  1. 70 |

    直接访问漏洞url即可下载数据库配置文件,观察浏览器右上角发现已经下载


71 |

配置文件截图:index.png


72 | """ 73 | 74 | files = { 75 | 'attachment': (None, ''), 76 | 'attachment_name': (None, ''), 77 | 'url': (None, url), 78 | 'attribute': (None, '1'), # 漏洞类型,1:事件 2:通用 79 | 'company_name': (None, company), 80 | 'host': (None, host), 81 | 'origin': (None, '1'), 82 | 'title': (None, company + '1网站存在数据库配置信息泄露'), 83 | 'active_id': (None, ''), # 活动id 84 | 'type': (None, '10'), # 漏洞类型 67弱口令 10信息泄露 85 | 'level': (None, '1'), # 漏洞等级 2:高危 86 | 'description': (None, company + '关联网站存在数据库账号密码明文信息泄露'), 87 | 'detail': (None, detail), 88 | 'repair_suggest': (None, '加强拦截策略,不允许接口访问'), 89 | 'tag3': (None, 'class1|18,class2|19'), 90 | 'province': (None, '青海省'), # 所属地区 省 91 | 'city': (None, '西宁市'), # 所属地区 市 92 | 'county': (None, '市辖区'), 93 | 'company_contact': (None, ''), 94 | 'anonymous': (None, '1'), # 匿名提交 95 | 'agree': (None, '1'), # 是否同意用户协议 96 | 'id': (None, ''), # 未知属性 97 | 'geetest_challenge': (None, challenge), 98 | 'geetest_validate': (None, validate), 99 | 'geetest_seccode': (None, validate + '|jordan') 100 | } 101 | try: 102 | url_but = "https://www.butian.net/Home/Loo/submit" 103 | rsp = session.post(url=url_but, files=files, headers=headers, verify=False, 104 | timeout=15, proxies=proxies) 105 | except: 106 | return but_submit(url, domain) 107 | # print(rsp.text) 108 | data = json.loads(rsp.text) 109 | if "QTVA" in data["data"]: 110 | print(f"补天成功提交{company}") 111 | pass 112 | elif data["info"] == "\u64cd\u4f5c\u8fc7\u4e8e\u9891\u7e41\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5": 113 | # print(f"{url}操作过于频繁") 114 | sleep(random.randint(20, 30)) 115 | but_submit(url, domain) 116 | elif rsp.status_code == 302: 117 | print(f"补天COOKIE失效") 118 | pass 119 | else: 120 | print(f'补天{data["info"]}') 121 | pass 122 | 123 | # but_submit("http://1.14.8.252:8088/808gps/MobileAction_downLoad.action?path=/WEB-INF/classes/config/jdbc.properties", 124 | # "mingshang.cc") 125 | --------------------------------------------------------------------------------