文章总结: 本文介绍如何使用Python自动化漏洞狩猎工具开发,通过自定义IDOR扫描器和子域名爆破工具提升漏洞发现效率10倍。文章包含环境配置、HTTP请求基础、会话管理、多线程实现等实战代码,强调定制化工具在漏洞赏金活动中的独特优势。 综合评分: 85 文章分类: WEB安全,安全工具,安全开发,渗透测试,红队
用Python自动化漏洞狩猎,打造专属工具,让狩猎速度提升10倍!
haidragon haidragon
安全狗的自我修养
2026年5月6日 12:24 湖南
在小说阅读器读本章
去阅读
#
官网:http://securitytech.cc
#
今天学什么?
- 漏洞赏金的 Python 基础知识——快速回顾
- 针对HTTP请求发起攻击
- 创建自定义的IDOR扫描器
- 创建子域名暴力破解工具
- 创建API密钥暴露扫描器
- 多线程速度提升10倍
- 完整的重建自动化流水线
为什么一定要这么做? 手动测试 = 慢 = 缺少漏洞!Python自动化 = 10倍速度 = 10倍漏洞 = 10倍赏金!顶尖猎手们会开发自己的定制工具,去挖掘那些通用工具遗漏的细节!这是高级系列的第一篇文章,从今以后,我们不仅要做猎手,还要成为工具开发者!
为什么我的漏洞赏金是Python?
1. 通用工具(Nuclei、Subfinder等):
3. →所有猎人都拥有
5. →相同结果=重复风险 zyada!
6. →无法自定义逻辑,我的Python工具:
8. →只有你才有!
10. →自定义逻辑=独特的漏洞!
11. →针对特定目标进行优化
13. →多种技术串联起来
15. →可以集成AI!真正差异:
17. 100个猎人核心正在狩猎=相同结果
19. 1款猎人定制Python工具,挑战来袭!=独一无二!Python=漏洞赏金的秘密武器!🐍
第一部分:设置环境,准备Karo
1. # 检查 Python 3.10+:
3. python3 --version# 创建虚拟环境(最佳实践!):
4. python3 -m venv bugbounty_env
5. 来源 bugbounty_env/bin/activate
6. # Windows: bugbounty_env\Scripts\activate# 一次性安装必备库:
7. pip 安装 requests \
8. httpx \
9. aiohttp \
10. BeautifulSoup4
11. lxml \
12. 颜色ama \
13. 丰富的
14. tqdm \
15. python-dotenv \
16. argparse# 验证安装:
17. python3 -c "import requests, colorama, rich; \
19. print('✅ 所有库已就绪!')
第二部分:HTTP请求基础 学习一下
基本请求:
1. import requests# ─── GET请求 ──────────────────────────
3. r = requests.get("https://target.com/api/user")
4. print(r.status_code)# 200、401、403、500……
5. print(r.text)# 完整响应体
6. print(r.json())# JSON解析(如果为JSON格式)
7. print(r.headers)# 响应头
8. print(r.cookies)# Cookies# ─── 带参数的GET请求 ──────────────────
9. 参数={"id":"1001","format":"json"}
10. r = requests.get(
11. “https://target.com/api/user”,
12. 参数=参数
13. )
14. # 最终URL:/api/user?id=1001&format=json# ─── 使用JSON的POST请求──────────────────────
15. 数据={"用户名":"admin","密码":"test123"}
16. r = requests.post(
17. “https://target.com/login”,
18. json=数据,# 自动内容类型:JSON
19. 超时=10
20. )#───包含头信息与Cookie的完整请求──
21. 头部={
22. “授权”:“Bearer YOUR_JWT_TOKEN”,
23. “用户代理”:Mozilla/5.0(X11;Linux x86_64)
24. “X-Forwarded-For”:“127.0.0.1”
25. }
26. cookies ={"session":"ABC123XYZ"}r = requests.get(
27. “https://target.com/api/dashboard”
28. headers=headers,
29. 饼干=饼干,
30. verify=False,# 跳过SSL检查(仅用于测试!)
31. 超时=10,
32. 允许重定向=True
34. )
会话对象 Cookie 自动管理:
1. import requests# 会话 = 登录一次——所有请求都用这个会话
3. # 自动化Cookie保持!session = requests.Session()# 第一步:登录
5. 会话.post(
7. “https://target.com/login”,
9. json={"用户":"[email protected]",
11. “密码”:“mypassword123”}
13. )
15. # ✅ 会话Cookie自动保存!# 第二步:经过身份验证的请求——Cookie自动附加!
17. r1 =会话.get("https://target.com/api/profile/1002")
19. r2 =会话.get("https://target.com/api/invoices/9876")
21. r3 = session.get("https://target.com/api/messages/555")print(r1.text)# 受害者个人资料——IDOR测试!
23. print(r2.text)# 受害者的发票!
24. print(r3.text)# 私密消息!# ─── Requests 忽略 SSL 警告 ─────────
26. 导入urllib3
28. urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
第三部分:打造属于你的自定义IDOR扫描器!
1. #!/usr/bin/env python3
3. """
5. IDOR扫描器v2.0 — HackerMD
7. 测试数字 + UUID ID 参数
python import requests
1. 导入 json
3. 导入时间
4. 来自colorama的Fore、Style和init
5. import urllib3urllib3.disable_warnings()
6. init(autoreset=True)类IDORScanner:
7. def __init__(self, base_url, token,
8. 我的ID,ID范围=(1,200),
9. 延迟=0.1):
10. self.base_url = base_url
11. self.my_id = my_id
12. self.id_range = id_range
13. self.delay =延迟
14. self.session = requests.Session()
15. self.session.headers.update({
16. “授权”: f“Bearer{token}”,
17. “用户代理”:“Mozilla/5.0”
18. })
19. self.session.verify =False
20. self.脆弱=[]
21. self.errors =0def get_baseline(self):
22. 获取你的数据——基线长度
23. 尝试:
24. r =self.session.get(
25. f"{self.base_url}/{self.my_id}",
26. 超时=10
27. )
28. 返回 r.status_code, len(r.text)
29. 除Exception以外:
30. print(f"{Fore.YELLOW}⚠️ 基线错误:{e}")
31. 返回空值,0def test_single_id(self, test_id, base_len):
32. “测试单个ID”
33. 尝试:
34. r =self.session.get(
35. f"{self.base_url}/{test_id}",
36. 超时=10
37. )# 200 + 长度显著不同
38. # = 可能是不同用户的数据!
39. 长度差= abs(len(r.text)-基线长度)如果 r.status_code ==200且长度差>30:
40. 返回{
41. “id”:测试ID,
42. “状态”:r.status_code,
43. “长度”:len(r.text),
44. “差异”:长度差异,
45. “预览”:r.text[:150]
46. }
47. 除 requests.exceptions.Timeout之外:
48. self.errors +=1
49. 除了Exception作为 e:
50. self.errors +=1
51. 返回空def扫描(self):
52. 打印(f"
53. {Fore.CYAN}╔══════════════════════════════╗)
54. print(f"{Fore.CYAN}║ IDOR扫描器—HackerMD║")
55. print(f"{Fore.CYAN}╚══════════════════════════════╝")
56. 打印(f"目标:{self.base_url}")
57. print(f"我的ID :{self.my_id}")
58. print(f"范围:{self.id_range[0]}–{self.id_range[1]}")
59. print(f"延迟:{self.delay}秒")
60. print("─" * 40) # 基线
61. 基础状态,基础长度 = 自我获取基线()
62. 如果基础状态不存在:
63. print(f"{Fore.RED}❌无法连接目标!")
64. 返回 打印(f"基准:{base_status}|{base_len}字节")
65. ) # 扫描卡罗
66. 总和 = self.id_range[1] - self.id_range[0]
67. 对于 i,测试 ID in enumerate(
68. 范围(self.id_range[0], self.id_range[1]+1)
69. ):
70. 如果 test_id == self.my_id:
71. 继续 # 进度条
72. 进度 = int((i / 总数) * 30)
73. bar = “█” * 进度 + “░” * (30 - 进度)
74. 百分比 = 整数((i / 总数) × 100)
75. print(f"\r{Fore.CYAN}[{bar}]{pct}%|")
76. f"测试ID:{test_id}",
77. end="", flush=True) result = self.test_single_id(
78. 测试ID,基础长度
79. ) 如果结果:
80. 打印(f"
81. {Fore.RED}🔴可能存在IDOR!)
82. print(f" ID : {result['id']}")
83. print(f" 状态 : {result['status']}")
84. print(f" 长度 : {result['length']}")
85. f"(差值:{result['diff']})")
86. 打印(f" 预览:"
87. f"{result['preview'][:80]}...”
88. self.vulnerable.append(result) time.sleep(self.delay) # 总结
89. 打印(f"
90. {'─'*40}
91. print(f"✅ 扫描完成!")
92. 打印(f" 测试:{total} 个ID")
93. 打印(f" 找到 : "
94. f"{Fore.RED}{len(self.vulnerable)}"
95. “{Style.RESET_ALL}潜在的IDOR”
96. print(f" 错误 : {self.errors}")# 保存结果
97. 如果self.脆弱:
98. 输出文件=“idor_results.json”
99. with open(out_file,"w")as f:
100. json.dump(self.vulnerable, f, indent=2)
101. print(f" 已保存 : {out_file}")returnself.vulnerable# ─── 使用方法 ────────────────────────────────
102. 如果 __name__ =="__main__":
103. 扫描仪= IDOR扫描仪(
104. base_url ="https://target.com/api/v1/invoices",
105. 令牌=“您的认证令牌在这里”,
106. 我的ID =1050,
107. id_range =(1000,1150),
108. 延迟=0.1# 用于避免速率限制!
109. )
111. 扫描仪.扫描()
第4部分:多线程子域名爆破工具!
1. #!/usr/bin/env python3
3. """
5. 子域名暴力破解器 v2.0 — HackerMD
7. 快速多线程子域名发现
python import requests
1. 导入线程
3. 来自队列的队列
4. 来自colorama的Fore、Style和init
5. 导入时间
6. 导入 jsonurllib3 已导入=False
7. 尝试:
8. 导入urllib3
9. 禁用 urllib3 警告
10. urllib3已导入=True
11. 除了:
12. passinit(autoreset=True)类子域名爆破器:
13. def __init__(self, domain, wordlist_path,
14. 线程数=50,超时=5)
15. self.domain =域名
16. self.wordlist =self.load_wordlist(wordlist_path)
17. self.threads = threads
18. self.timeout =超时
19. self.queue =Queue()
20. self.found =[]
21. self.lock= threading.Lock()
22. self.checked=0
23. self.total = len(self.wordlist)
24. self.start_time =Nonedef load_wordlist(self, path):
25. 尝试:
26. with open(path,"r", errors="ignore")as f:
27. words =[line.strip()for line in f]
28. 如果行.strip()]
29. print(f"✅ 词表已加载:{len(words)} 个词")
30. 返回单词
31. 除了FileNotFoundError:
32. print(f"❌ 未找到字典文件:{path}")
33. # 默认小列表
34. 返回[
35. “www”、“mail”、“ftp”、“admin”、“api”,
36. “开发”、“测试”、“预发布”、“beta”、“旧版”,
37. 应用、门户、仪表板、安全、
38. “vpn”、“内部”、“备份”、“cdn”、“博客”,
39. 商店、店铺、支持、文档、Git
40. ]def check_subdomain(self, subdomain):
41. “检查单个子域名”
42. url = f"https://{子域名}.{self.domain}"
43. 尝试:
44. r = requests.get(
45. 网址,
46. 超时=self.超时,
47. 验证=False,
48. 允许重定向=True
49. )
50. 使用self.lock:
51. self.found.append({
52. “子域名”:f"{子域名}.{self.domain}",
53. “状态”:r.status_code,
54. “长度”:len(r.text),
55. “服务器”: r.headers.get(
56. “服务器”,“未知”
57. ),
58. “url”: url
59. })# 按状态码着色:
60. 如果 r.status_code ==200:
61. 颜色=前景.绿色
62. 如果 r.status_code 在[301,302]中:
63. 颜色=前景.黄色
64. 如果 r.status_code ==403:
65. 颜色=Fore.RED
66. 否则:
67. 颜色=前景.青色打印(
68. “{color}🔴[{r.status_code}]”
69. “{subdomain}.{self.domain}”
70. f"({r.headers.get('Server','')})"
71. )except requests.exceptions.ConnectionError:
72. 通过# 子域名不存在
73. 除了异常:
74. 通过
75. 最后:
76. 使用self.lock:
77. self.checked+=1def worker(self):
78. “线程工作者”
79. 无限循环:
80. 子域名=self.queue.get()
81. 如果子域名为空:
82. 中断
83. self.check_subdomain(子域名)
84. self.queue.task_done()def progress_monitor(self):
85. “进度显示线程”
86. 当self.checked<self.total 时:
87. 百分比=整数((已选/总数)×100)
88. 已用时=当前时间-自我开始时间
89. 速度=自我检查/最大(已用时,1)
90. 打印(
91. f"\r{Fore.CYAN}进度:{pct}% | "
92. f"已检查:{self.checked}/{self.total} | "
93. f"已找到:{len(self.found)} | "
94. f"速度:{speed:.0f}/秒 ",
95. end="", flush=True
96. )
97. time.sleep(0.5)def run(self):
98. 打印(f"
99. {Fore.CYAN}╔═══════════════════════════════╗")
100. print(f"{Fore.CYAN}║ 子域名爆破器 — HackerMD ║")
101. print(f"{Fore.CYAN}╚═══════════════════════════════╝")
102. 打印(f"域名:{self.domain}")
103. print(f"单词数量:{len(self.wordlist)}")
104. 打印(f"线程:{self.threads}")
105. print("─"*42)self.start_time = time.time()# 启动工作线程
106. 线程列表=[]
107. 对于 _ 在self.线程范围内:
108. t =线程.Thread(target=self.worker,
109. 守护进程=True)
110. t.start()
111. 线程列表.append(t)# 填充队列
112. 对于单词in自我单词列表:
113. self.queue.put(word)# 停止信号
114. 对于 _ 在self.线程范围内:
115. self.queue.put(None)# 等待
116. 对于线程列表中的每个t:
117. t.join()经过时间=时间.time()-self.start_time # 结果
118. 打印(f"
119. {'─' * 42}
120. print(f"✅完成!耗时:{elapsed:.1f}秒")
121. print(f"🔴找到:{len(self.found)}个子域名
122. ”)# 按状态排序
123. self.found.sort(key=lambda x: x["status"])
124. 对于 s 在self.found 中:
125. print(f" [{s['status']}] {s['subdomain']}")# 保存
126. with open(f"subs_{self.domain}.txt","w")as f:
127. 对于 s 在self.found 中:
128. f.write(
129. f"{s['子域名']} "
130. f"[{s['status']}]
131. ”
132. ) with open(f"subs_{self.domain}.json", "w") as f:
133. json.dump(self.found, f, indent=2) print(f"
134. 💾已保存:subs_{self.domain}.txt)
135. 返回self.found# ─── 用法 ────────────────────────────────
136. 如果 __name__ =="__main__":
137. bruter =子域名爆破器(
138. 域名=“target.com”,
139. 词汇表路径=(
140. “/usr/share/wordlists/SecLists/”
141. 发现/DNS/
142. 顶级百万子域名-5000.txt
143. ),
144. 线程=100,
145. 超时=4
146. )
148. 布鲁特.运行()
第5部分:秘密扫描器JS文件,我的秘密!
1. #!/usr/bin/env python3
3. """
5. 秘密扫描器 v2.0 — HackerMD
7. JS/配置文件中的API密钥、令牌和密钥
python import requests
1. 导入正则表达式
3. 导入 json
4. 来自colorama的Fore和initinit(autoreset=True)
5. requests.packages.urllib3.disable_warnings()#───秘密正则表达式模式────────────────
6. 模式={
7. “AWS访问密钥”:r"AKIA[0-9A-Z]{16}",
8. “AWS密钥”: r"(?i)aws.{0,20}secret.{0,20}['\"][0-9a-zA-Z/+]{40}['\"]",
9. “GitHub令牌”: r"ghp_[0-9a-zA-Z]{36}",
10. “GitHubClassic”:r"github_pat_[0-9a-zA-Z_]{82}”
11. “Google API密钥”:r"AIza[0-9A-Za-z\-_]{35}",
12. “Stripe密钥”:r"sk_live_[0-9a-zA-Z]{24,}",
13. “Stripe 发布”:r"pk_live_[0-9a-zA-Z]{24,}"
14. “Slack 令牌” : r"xox[baprs]-[0-9a-zA-Z\-]{10,48}",
15. “Twilio SID” : r"AC[a-zA-Z0-9]{32}",
16. “SendGrid密钥”:r“SG\.[a-zA-Z0-9\-_]{22}\.[a-zA-Z0-9\-_]{43}”,
17. “Firebase URL”:r"https://[a-z0-9-]+\.firebaseio\.com",
18. “JWT 令牌”: r"eyJ[A-Za-z0-9\-_=]+\.[A-Za-z0-9\-_=]+\.?[A-Za-z0-9\-_.+/=]*",
19. “私钥”: r"-----BEGIN (?:RSA |EC )?PRIVATE KEY",
20. “数据库连接”:r"(?:mysql|postgres|mongodb|redis|mssql)://[^\s\"'<>]+"
21. “通用密钥”:r"(?i)(?:secret_key|api_key|apikey|access_token|auth_token)\s*[=:]\s*['\"]([^'\"]{10,})['\"]"
22. “通用密码”:r"(?i)(?:password|passwd|pwd)\s*[=:]\s*['\"]([^'\"]{6,})['\"]",
23. }#───敏感文件路径──────────────────
24. 敏感路径=[
25. /.env、/.env.local、/.env.production、
26. /.env.backup、/config.js、/config.json、
27. “/settings.py”、“/app.js”、“/main.js”,
28. “/bundle.js”,“/webpack.config.js”,
29. “/api/config”,“/api/settings”,
30. /.git/config,/web.config,
31. “/phpinfo.php”,“/info.php”,
32. “/server-status”,“/server-info”,
33. “/actuator/env”,“/actuator/configprops”,
34. “/api/v1/config”,“/api/v2/config”,
35. ]类SecretScanner:
36. def __init__(self, domain):
37. self.domain = domain
38. self.base_url = f"https://{domain}"
39. self.session = requests.Session()
40. self.session.verify =False
41. self.session.headers.update({
42. “用户代理”:Mozilla/5.0(X11;Linux x86_64)
43. })
44. self.findings =[]
45. self.js_urls =[]def extract_js_urls(self):
46. “从主页获取JS文件URL”
47. 尝试:
48. r =self.session.get(
49. self.base_url,超时=10
50. )
51. # src="..." 模式
52. 模式= r'src=["\']([^"\']*\.js(?:\?[^"\']*)?)["\']'
53. 匹配项= re.findall(模式, r.text)对于 m 在匹配项中:
54. 如果 m 以“http”开头:
55. self.js_urls.append(m)
56. 如果 m 以“//”开头:
57. self.js_urls.append(f"https:{m}")
58. elif m.startswith("/"):
59. self.js_urls.append(
60. f"{self.base_url}{m}"
61. )print(f"✅ 找到 {len(self.js_urls)} 个 JS 文件")
62. 除了Exception作为 e:
63. print(f"❌ 提取JS时出错:{e}")def scan_content(self, content, source):
64. “在内容中寻找秘密”
65. 已找到此处=[]
66. 对于 secret_type, pattern in PATTERNS.items():
67. 匹配= re.findall(模式,内容)
68. 对于比赛中的每场比赛:
69. 值=匹配如果 isinstance(匹配, str) \
70. 否则返回 match[0],如果 match 为空则返回空字符串。
71. 如果长度大于等于8:
72. 查找={
73. “类型”:密钥类型,
74. “值”:val[:60]+(“…”if len(val)>60else“”),
75. “来源”:来源
76. }
77. 如果未在self.findings中找到:
78. self.findings.append(发现)
79. 已找到的添加到此处.append(发现)
80. 打印(
81. f" {Fore.RED}🔴 {secret_type}"
82. f”
83. {val[:55]}...
84. )
85. 返回已找到def扫描_js文件(self):
86. 扫描所有JS文件
87. 打印(f"
88. {Fore.YELLOW}[2/3] 正在扫描JS文件...)
89. 对于 self.js_urls 中的每个 URL:# 最多 20 个文件
90. 尝试:
91. r = self.session.get(url, timeout=8)
92. 文件名 = URL.split("/")[-1].split("?")[0]
93. print(f"检查:{fname[:40]}")
94. self.scan_content(r.text, url)
95. 除了:
96. 通过 def scan_sensitive_paths(self):
97. “检查敏感路径”
98. 打印(f"
99. {Fore.YELLOW}[3/3]正在扫描敏感路径...
100. 对于路径in敏感路径:
101. url = f"{self.base_url}{path}"
102. 尝试:
103. r =self.session.get(
104. 网址,超时=5,
105. 允许重定向=False
106. )
107. 如果 r.status_code ==200:
108. 大小= len(文本)
109. 打印(
110. f" {Fore.GREEN}✅ [200] "
111. “{path}({size}字节)”
112. )
113. self.scan_content(r.text, url)# .env 是否泄露?
114. 如果路径中包含“.env”且大小大于10:
115. 打印(
116. f" {Fore.RED}🔴🔴 "
117. f“.ENV文件已暴露!{url}”
118. )
119. 除了:
120. 传递def run(self):
121. 打印(f"
122. {Fore.CYAN}╔══════════════════════════════╗)
123. print(f"{Fore.CYAN}║密码扫描器—HackerMD║")
124. print(f"{Fore.CYAN}╚══════════════════════════════╝")
125. 打印(f"目标:{self.domain}")
126. ) print(f"{Fore.YELLOW}[1/3]提取JS文件...")
127. self.extract_js_urls()
128. self.scan_js_files()
129. self.scan_sensitive_paths() # ─── 最终报告 ─────────────────
130. 打印(f"
131. {'─'*42}**
132. print(f"✅ 扫描完成!")
133. print(f" 找到的密钥:"
134. f"{Fore.RED}{len(self.findings)}")如果self.findings:
135. out= f"secrets_{self.domain}.json"
136. with open(out,"w")as f:
137. json.dump(self.findings, f, indent=2)
138. print(f" 已保存:{out}")# 按类型汇总
139. 打印(f"
140. {Fore.RED}📋 摘要:)
141. 类型 = {}
142. 对于 f_item in self.findings:
143. t = f_item["类型"]
144. types[t] = types.get(t, 0) + 1
145. 对于 t,计数 in types.items():
146. print(f"{t}:{count}") return self.findings# ─── 使用方法 ────────────────────────────────
147. 如果 __name__ == "__main__":
148. 导入系统
149. 域名 = sys.argv[1] 如果 len(sys.argv) > 1 \
150. 否则“target.com”
151. 扫描器 = 秘密扫描器(域名)
153. 扫描仪运行()
第6部分:异步扫描速度提升10倍!
1. #!/usr/bin/env python3
3. """
5. 异步URL扫描器 — HackerMD
7. aiohttp 10倍速并行扫描
python import asyncio
1. 导入aiohttp
3. 导入 json
4. 导入时间
5. from colorama importFore, initinit(autoreset=True)asyncdef check_url(session, url, semaphore):
6. “单URL异步检查”
7. 异步使用信号量:
8. 尝试:
9. 异步与会话.get(
10. 网址,
11. 超时=aiohttp.ClientTimeout(总超时=6),
12. ssl=False,
13. 允许重定向=False
14. )作为回应:
15. 文本=await resp.text(
16. 错误="忽略"
17. )
18. 返回{
19. “url”: url,
20. “状态”:resp.状态,
21. “长度”:len(文本),
22. “服务器”:resp.headers.get(
23. “服务器”,“”
24. ),
25. “标题”:文本[
26. text.find("<title>")+7:
27. 文本.find("</title>")
28. [:60]如果“<title>”在文本中,则返回;否则返回空字符串。
29. }
30. 除了:
31. 返回Noneasyncdef async_scan(urls, max_concurrent=150,
32. 仅限有趣=True):
33. “并行扫描所有URL”信号量= asyncio.Semaphore(最大并发数)
34. 连接器= aiohttp.TCPConnector(
35. 限制=最大并发,SSL=False
36. )
37. 结果=[]打印(f"
38. {Fore.CYAN}╔══════════════════════════════╗)
39. print(f"{Fore.CYAN}║异步扫描器—HackerMD║")
40. print(f"{Fore.CYAN}╚══════════════════════════════╝")
41. print(f"URLs:{len(urls)}")
42. 打印(f"并发:{max_concurrent}")
43. print("─" * 42) 开始 = 时间.time() 异步 with aiohttp.ClientSession(
44. 连接器=连接器,
45. headers={"User-Agent": "Mozilla/5.0"}
46. ) 作为会话:
47. 任务 = [
48. 检查URL(会话,URL,信号量)
49. 对于url in urls
50. ]
51. responses = await asyncio.gather(
52. *任务,返回异常=True
53. ) for resp in responses:
54. 如果 resp 为空或 resp 是异常类型:
55. 继续 状态 = 响应["状态"]
56. 如果仅限有趣且 \
57. 状态不在 [200, 301, 302, 403] 中:
58. 继续 results.append(响应) # 按状态着色:
59. 如果状态码等于200:
60. 颜色 = 前景.绿色
61. 如果状态码为403:
62. 颜色 = Fore.RED
63. 如果状态在[301, 302]中:
64. 颜色 = 前景.黄色
65. 否则:
66. 颜色 = 红色.青色 打印(
67. “{color}[{status}] ”
68. f"{resp['length']:6d}字节|"
69. f"{resp['url']}"
70. + (f"|{resp['title']}")
71. 如果 resp['title'] 不存在,则返回空字符串
72. ) 经过时间 = 时间.time() - 开始
73. 速度 = URL数量 / 最大(已用时,0.1) print(f"
74. {'─'*42}
75. print(f"✅ 完成!耗时:{elapsed:.2f}秒 | ")
76. f"速度:{speed:.0f} 请求/秒")
77. print(f"找到:{len(results)} 个有趣的URL")return results# ─── 使用方法 ────────────────────────────────
78. 如果 __name__ =="__main__":
79. 基础=“https://target.com”
80. 路径=[
81. “/admin”、“/api/v1/users”、“/dashboard”,
82. /.env、/.git/HEAD、/swagger.json、
83. “/api-docs”、“/actuator”、“/debug”
84. “/config”、“/backup”、“/phpinfo.php”,
85. “/api/v2/users”,“/internal/admin”
86. “/api/v1/config”,“/api/health”,
87. ]
88. urls =[f"{BASE}{p}"for p in PATHS] results = asyncio.run(
89. 异步扫描(urls,最大并发=100)
90. )# 保存
91. with open("async_results.json","w")as f:
93. json.dump(结果, f,缩进=2)
第7部分:完成侦察管道,萨布组合!
1. #!/usr/bin/env python3
3. """
5. 完整侦察流程 v2.0 — HackerMD
7. 通过命令实现全面的侦察自动化!
python import subprocess
1. 导入 requests
3. 导入 json
4. 导入 os
5. 导入 asyncio
6. 导入aiohttp
7. 从 datetime import datetime
8. 来自colorama的Fore和initinit(autoreset=True)
9. requests.packages.urllib3.disable_warnings()类ReconPipeline:
10. def __init__(self, domain):
11. self.domain = domain
12. self.ts = datetime.now().strftime(
13. “%Y%m%d_%H%M”
14. )
15. self.out_dir = f"recon_{domain}_{self.ts}"
16. os.makedirs(self.out_dir, exist_ok=True)
17. self.session = requests.Session()
18. self.session.verify =False
19. self.results ={
20. “域名”:域名,
21. “时间戳”:self.ts,
22. “子域名”:[],
23. “live_hosts”:[]
24. “秘密”:[]
25. “有趣”:[],
26. “技术”:[]
27. }def run_cmd(self, cmd, timeout=60):
28. “运行Shell命令”
29. 尝试:
30. 输出=子进程.run(
31. 命令,shell=True,
32. 捕获输出=True,
33. 文本=真,超时=超时
34. )
35. 返回out.stdout.strip()
36. 除 subprocess.TimeoutExpired以外:
37. 返回“”
38. 除了异常:
39. 返回“”# ─── 第1步:子域名发现 ──────
40. def step1子域名(self):
41. 打印(f"
42. {Fore.CYAN}[1/5] 🌐 子域名发现)
43. out_file = f"{self.out_dir}/subdomains.txt" output = self.run_cmd(
44. f"subfinder -d {self.domain}-silent 2>/dev/null"
45. ) 如果输出:
46. subs = [s for s in output.split('
47. ') 如果 s]
48. self.results["子域名"] = 子域名列表
49. with open(out_file, "w") as f:
50. f.write(输出)
51. print(f"✅找到:{len(subs)}个子域名")
52. 否则:
53. 常见 = [
54. f"www.{self.domain}",
55. f"api.{self.domain}",
56. f"dev.{self.domain}",
57. f"admin.{self.domain}",
58. f"邮件.{self.domain}",
59. f"暂存.{self.domain}",
60. ]
61. self.results["子域名"] = 公共
62. with open(out_file, "w") as f:
63. f.write("
64. “.join(公共)”
65. print(f" ⚠️ subfinder 未找到 — "
66. f"使用 {len(common)} 个公共子串")# ─── 第二步:实时主机过滤 ──────
67. def step2_live_hosts(self):
68. 打印(f"
69. {Fore.CYAN}[2/5] 🔥 直播主持人检查)
70. 子文件 = f"{self.out_dir}/subdomains.txt"
71. live_file = f"{self.out_dir}/live_hosts.txt" 如果子文件不存在:
72. 打印("❌子域名文件缺失!")
73. 返回 live_out = self.run_cmd(
74. f"猫{sub_file}| httpx -silent "
75. f"-mc 200,301,302,4032>/dev/null",
76. 超时=120
77. ) 如果 live_out:
78. 主机 = [h for h in live_out.split('
79. ') 如果 h]
80. self.results["live_hosts"] = 主机
81. with open(live_file, "w") as f:
82. f.write(直播输出)
83. print(f"✅在线主机:{len(hosts)}")
84. 否则:
85. print("⚠️ httpx未找到——跳过") # ─── 第3步:技术检测───────────
86. def step3_技术检测(self):
87. 打印(f"
88. {Fore.CYAN}[3/5]🔍技术检测)
89. 尝试:
90. r =self.session.get(
91. f"https://{self.domain}",
92. 超时=10
93. )
94. 技术=[]
95. headers = r.headers 服务器= headers.get("Server","")
96. 如果服务器:
97. techs.append(f"服务器:{server}")
98. 如果“X-Powered-By”在标头中:
99. 技术员.append(
100. f"由 {headers['X-Powered-By']} 提供支持"
101. )
102. 如果“X-Generator”在标头中:
103. 技术员.append(
104. f"生成器:{headers['X-Generator']}"
105. )正文= r.text.lower()
106. 如果“wp-content”在正文中:
107. 技术栈.append("WordPress")
108. 如果“drupal”在正文中:
109. 技术栈.append("Drupal")
110. 如果正文包含“react”或“__react”:
111. techs.append("ReactJS")
112. 如果“angular”在正文中:
113. 技术栈.append("AngularJS")
114. 如果“laravel”在正文中:
115. 技术栈.append("Laravel")
116. 如果“django”在正文中:
117. techs.append("Django")缺失=[]
118. for h in["内容安全策略",
119. X-框架选项,
120. X-XSS-保护,
121. “严格传输安全”:
122. 如果 h 不在 headers 中:
123. missing.append(h)self.results["technologies"]= techs
124. 如果缺失:
125. self.results["interesting"].append(
126. f“缺少安全标头:”
127. f"{', '.join(missing)}"
128. )for技术in技术们:
129. 打印(f" 📦 {t}")
130. 如果缺失:
131. print(f" {Fore.YELLOW}⚠️ 缺失的标题:")
132. f"{len(missing)}")除了Exceptionas e:
133. print(f" ❌ 错误:{e}")# ─── 第4步:快速密钥扫描 ────────
134. def step4_secrets(self):
135. 打印(f"
136. {Fore.CYAN}[4/5] 🔑 快速秘密扫描)
137. 导入 re 快速模式 = {
138. “AWS密钥”:r“AKIA[0-9A-Z]{16}”,
139. “GitHub” : r"ghp_[0-9a-zA-Z]{36}",
140. “Stripe”:r"sk_live_[0-9a-zA-Z]{24}",
141. “谷歌API”:r"AIza[0-9A-Za-z\-_]{35}",
142. “JWT” : r"eyJ[A-Za-z0-9\-_=]{10,}\.",
143. } 检查网址 = [
144. f"https://{self.domain}/.env",
145. f"https://{self.domain}/config.js",
146. f"https://{self.domain}/main.js",
147. ]for url in check_urls:
148. 尝试:
149. r =self.session.get(url, timeout=6)
150. 如果 r.status_code ==200:
151. 对于名称,模式in \
152. 快速模式.项():
153. 匹配= re.findall(
154. 模式,r.text
155. )
156. 对于 m 在 matches 中:
157. 查找=(
158. “{name}在{url}:”
159. “{m[:30]}…”
160. )
161. self.results[
162. 秘密
163. ].追加(发现)
164. 打印(
165. f" {Fore.RED}"
166. f"🔴 {finding}"
167. )
168. 除了:
169. 通过如果self.results["secrets"]为空:
170. print(f" {Fore.GREEN}✅ 没有发现快速秘诀")# ─── 第5步:生成报告 ──────────
171. def step5_report(self):
172. 打印(f"
173. {Fore.CYAN}[5/5] 📝 生成报告”) report = f"{self.out_dir}/recon_report.json"
174. with open(report, "w") as f:
175. json.dump(self.results, f, indent=2) print(f"
176. {Fore.CYAN}╔══════════════════════════════════╗")
177. print(f"{Fore.CYAN}║侦察完成—HackerMD║")
178. print(f"{Fore.CYAN}╚══════════════════════════════════╝")
179. print(f"🌐子域名:")
180. f"{len(self.results['subdomains'])}"
181. print(f"🔥实时主播:")
182. f"{len(self.results['live_hosts'])}"
183. print(f"📦技术:"
184. f"{len(self.results['technologies'])}"
185. print(f"🔑找到的密钥:")
186. f"{Fore.RED}"
187. f"{len(self.results['secrets'])}"
188. print(f"📍有趣:")
189. f"{len(self.results['interesting'])}"
190. 打印(f"
191. 💾报告:{report})
192. print(f" 📂 目录 : {self.out_dir}/")def run(self):
193. 打印(f"
194. {Fore.CYAN}{'═' * 42}**
195. print(f"{Fore.CYAN}🚀侦察管道—HackerMD")
196. print(f"目标:{self.domain}")
197. print(f"{Fore.CYAN}{'═'*42}") self.step1_subdomains()
198. self.step2_实时主机()
199. self.step3_tech_detect()
200. self.step4_secrets()
201. self.step5_report()# ─── 使用方法 ────────────────────────────────
202. 如果 __name__ == "__main__":
203. 导入系统
204. 域名 = sys.argv[1] 如果 len(sys.argv) > 1 \
205. 否则“example.com”
206. 管道 = 重建管道(域名)
208. 流水线运行()
只需一条命令,搞定一切!
1. python3 recon_pipeline.py target.com
工具概要
1. 工具|用例|文件
3. -------------------|----------------------|--------------------
5. IDOR扫描器| IDOR ID测试| idor_scanner.py
7. 子域名爆破器|子域名暴力破解| sub_bruter.py
9. SecretScanner| JS/.env 中的 API 密钥| secret_scanner.py
11. 异步扫描器|快速批量URL检查| async_scanner.py
13. 重建管道|全自动化|重建管道.py
今天的作业
1. # 1. 环境搭建:
3. python3 -m venv bugenv
5. 来源 bugenv/bin/activate
7. pip 安装 requests aiohttp colorama rich tqdm# 2. 测试 Secret Scanner(合法目标!):
9. python3 secret_scanner.py testphp.vulnweb.com# 3. 异步扫描器测试:
11. python3 async_scanner.py
13. # 在URL列表中添加httpbin.org路径# 4. 运行侦察流水线:
15. python3 recon_pipeline.py hackerone.com
17. # (仅公开信息——合法!)# 5. 升级您的Apna:
19. 在IDORScanner中添加 UUID 支持。
20. # 在SecretScanner中添加Slack webhook模式
22. # 将SubdomainBruter的DNS解析添加到您的DNS中
快速复习
1. 🐍Python=漏洞赏金自动化利器!
3. 📦库= requests, aiohttp, colorama,
5. 丰富,tqdm,json
7. 🔍 IDOR扫描器= ID范围→不同响应= IDOR!
8. 🌍SubBruter=线程+字典=快速!
10. 🔑SecretScan=正则表达式模式→ JS/.env 密钥
12. ⚡异步扫描器= aiohttp + asyncio =10倍速度!
14. 🚀流程=萨布组合=全自动侦察!
16. 💰结果=自定义工具=独特漏洞=
18. 重复次数越少,奖励越多!
我的谈话……
起初,我都是手动测试每个端点的。
目标在6到8小时内完成。 Python自动化之后:
1. python3 recon_pipeline.py target.com
15分钟内:
- 发现847个子域名
- 134位直播主持人
- 暴露了 3 个
.env文件! - 找到 2 个管理面板(403)
在我的 .env 文件中:
1. STRIPE_SECRET=sk_live_xxxxxxxxxxxxxxxxxx
3. AWS_ACCESS_KEY_ID=AKIAXXXXXXXXXXXXXXXX
5. DB_PASSWORD=超级秘密2024!
手册卡片需要2到3天!3份独立报告:
.env泄露 = 2,500 美元- AWS密钥 = 3,200美元
- 条纹密钥 = 1,500美元
总计:15分钟自动化操作,节省7,200美元! 🎉
课程:在Python中投资一次,打造一个工具,反复使用,回报率无限! 在另一篇文章中,我将向大家介绍Gemini CLI + AI漏洞狩猎,打造2026年最强大的AI助手组合!🤖🔥
-
-
公众号:安全狗的自我修养
-
vx:2207344074
-
http://gitee.com/haidragon
-
http://github.com/haidragon
-
bilibili:haidragonx
-
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:安全狗的自我修养 haidragon haidragon《用Python自动化漏洞狩猎,打造专属工具,让狩猎速度提升10倍!》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论