hb-recon 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hb_recon-1.0.0/LICENSE +21 -0
- hb_recon-1.0.0/PKG-INFO +104 -0
- hb_recon-1.0.0/README.md +73 -0
- hb_recon-1.0.0/hb_recon/__init__.py +13 -0
- hb_recon-1.0.0/hb_recon/__main__.py +8 -0
- hb_recon-1.0.0/hb_recon/cli.py +395 -0
- hb_recon-1.0.0/hb_recon.egg-info/PKG-INFO +104 -0
- hb_recon-1.0.0/hb_recon.egg-info/SOURCES.txt +12 -0
- hb_recon-1.0.0/hb_recon.egg-info/dependency_links.txt +1 -0
- hb_recon-1.0.0/hb_recon.egg-info/entry_points.txt +2 -0
- hb_recon-1.0.0/hb_recon.egg-info/requires.txt +4 -0
- hb_recon-1.0.0/hb_recon.egg-info/top_level.txt +1 -0
- hb_recon-1.0.0/pyproject.toml +51 -0
- hb_recon-1.0.0/setup.cfg +4 -0
hb_recon-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hlaing Bwar
|
|
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.
|
hb_recon-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hb-recon
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Automated reconnaissance tool with AI report generation. Subdomain enumeration, endpoint crawling, and vulnerability pattern detection.
|
|
5
|
+
Author-email: Hlaing Bwar <infohlaingbwar@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/infohlaingbwar/hb-recon
|
|
8
|
+
Project-URL: Repository, https://github.com/infohlaingbwar/hb-recon
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/infohlaingbwar/hb-recon/issues
|
|
10
|
+
Keywords: recon,reconnaissance,osint,bug-bounty,pentesting,subdomain,enumeration,security,ethical-hacking
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Intended Audience :: Information Technology
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Security
|
|
22
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
23
|
+
Classifier: Operating System :: MacOS
|
|
24
|
+
Requires-Python: >=3.8
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
29
|
+
Requires-Dist: black>=22.0; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# HB-Recon
|
|
33
|
+
|
|
34
|
+
**Automated reconnaissance tool with AI-ready report generation.**
|
|
35
|
+
|
|
36
|
+
Perfect for bug bounty hunters, pentesters, and security researchers.
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
✅ **Subdomain Enumeration** — subfinder integration
|
|
41
|
+
✅ **Live Host Detection** — httpx for alive checks
|
|
42
|
+
✅ **Technology Stack Scan** — WhatWeb detection
|
|
43
|
+
✅ **Endpoint Crawling** — Katana deep crawl
|
|
44
|
+
✅ **Vulnerability Patterns** — gf (XSS, SQLi, IDOR detection)
|
|
45
|
+
✅ **AI Report Generation** — Structured JSON output
|
|
46
|
+
|
|
47
|
+
## Requirements
|
|
48
|
+
|
|
49
|
+
**External Tools (must be installed):**
|
|
50
|
+
- [subfinder](https://github.com/projectdiscovery/subfinder)
|
|
51
|
+
- [httpx](https://github.com/projectdiscovery/httpx)
|
|
52
|
+
- [katana](https://github.com/projectdiscovery/katana)
|
|
53
|
+
- [gf](https://github.com/tomnomnom/gf)
|
|
54
|
+
- [whatweb](https://github.com/urbanadventurer/WhatWeb)
|
|
55
|
+
|
|
56
|
+
**Install tools:**
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
## Install
|
|
60
|
+
|
|
61
|
+
Defaulting to user installation because normal site-packages is not writeable
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
**Example:**
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
**Output Structure:**
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
## AI Report
|
|
74
|
+
|
|
75
|
+
The tool generates with:
|
|
76
|
+
- Target info
|
|
77
|
+
- Discovered subdomains & endpoints
|
|
78
|
+
- Technology stack
|
|
79
|
+
- Risk-scored vulnerabilities
|
|
80
|
+
- Attack surface summary
|
|
81
|
+
|
|
82
|
+
Perfect for feeding into AI tools like ChatGPT, Claude for analysis.
|
|
83
|
+
|
|
84
|
+
## Example Workflow
|
|
85
|
+
|
|
86
|
+
Defaulting to user installation because normal site-packages is not writeable
|
|
87
|
+
|
|
88
|
+
## Security Notice
|
|
89
|
+
|
|
90
|
+
⚠️ **Only use on authorized targets.** Unauthorized scanning is illegal.
|
|
91
|
+
|
|
92
|
+
## License
|
|
93
|
+
|
|
94
|
+
MIT License - See [LICENSE](LICENSE)
|
|
95
|
+
|
|
96
|
+
## Author
|
|
97
|
+
|
|
98
|
+
**Hlaing Bwar**
|
|
99
|
+
- GitHub: [@infohlaingbwar](https://github.com/infohlaingbwar)
|
|
100
|
+
- Website: [hlaingbwar.com](https://www.hlaingbwar.com)
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
**Made with ❤️ for the bug bounty community**
|
hb_recon-1.0.0/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# HB-Recon
|
|
2
|
+
|
|
3
|
+
**Automated reconnaissance tool with AI-ready report generation.**
|
|
4
|
+
|
|
5
|
+
Perfect for bug bounty hunters, pentesters, and security researchers.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
✅ **Subdomain Enumeration** — subfinder integration
|
|
10
|
+
✅ **Live Host Detection** — httpx for alive checks
|
|
11
|
+
✅ **Technology Stack Scan** — WhatWeb detection
|
|
12
|
+
✅ **Endpoint Crawling** — Katana deep crawl
|
|
13
|
+
✅ **Vulnerability Patterns** — gf (XSS, SQLi, IDOR detection)
|
|
14
|
+
✅ **AI Report Generation** — Structured JSON output
|
|
15
|
+
|
|
16
|
+
## Requirements
|
|
17
|
+
|
|
18
|
+
**External Tools (must be installed):**
|
|
19
|
+
- [subfinder](https://github.com/projectdiscovery/subfinder)
|
|
20
|
+
- [httpx](https://github.com/projectdiscovery/httpx)
|
|
21
|
+
- [katana](https://github.com/projectdiscovery/katana)
|
|
22
|
+
- [gf](https://github.com/tomnomnom/gf)
|
|
23
|
+
- [whatweb](https://github.com/urbanadventurer/WhatWeb)
|
|
24
|
+
|
|
25
|
+
**Install tools:**
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
Defaulting to user installation because normal site-packages is not writeable
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
**Example:**
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
**Output Structure:**
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
## AI Report
|
|
43
|
+
|
|
44
|
+
The tool generates with:
|
|
45
|
+
- Target info
|
|
46
|
+
- Discovered subdomains & endpoints
|
|
47
|
+
- Technology stack
|
|
48
|
+
- Risk-scored vulnerabilities
|
|
49
|
+
- Attack surface summary
|
|
50
|
+
|
|
51
|
+
Perfect for feeding into AI tools like ChatGPT, Claude for analysis.
|
|
52
|
+
|
|
53
|
+
## Example Workflow
|
|
54
|
+
|
|
55
|
+
Defaulting to user installation because normal site-packages is not writeable
|
|
56
|
+
|
|
57
|
+
## Security Notice
|
|
58
|
+
|
|
59
|
+
⚠️ **Only use on authorized targets.** Unauthorized scanning is illegal.
|
|
60
|
+
|
|
61
|
+
## License
|
|
62
|
+
|
|
63
|
+
MIT License - See [LICENSE](LICENSE)
|
|
64
|
+
|
|
65
|
+
## Author
|
|
66
|
+
|
|
67
|
+
**Hlaing Bwar**
|
|
68
|
+
- GitHub: [@infohlaingbwar](https://github.com/infohlaingbwar)
|
|
69
|
+
- Website: [hlaingbwar.com](https://www.hlaingbwar.com)
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
**Made with ❤️ for the bug bounty community**
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""
|
|
2
|
+
HB-Recon - Automated reconnaissance tool with AI report generation
|
|
3
|
+
Author: Hlaing Bwar (https://github.com/infohlaingbwar)
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
__version__ = "1.0.0"
|
|
7
|
+
__author__ = "Hlaing Bwar"
|
|
8
|
+
__email__ = "infohlaingbwar@gmail.com"
|
|
9
|
+
__license__ = "MIT"
|
|
10
|
+
|
|
11
|
+
from .cli import main
|
|
12
|
+
|
|
13
|
+
__all__ = ["main"]
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
import json
|
|
4
|
+
import subprocess
|
|
5
|
+
import time
|
|
6
|
+
import concurrent.futures
|
|
7
|
+
from urllib.parse import urlparse, parse_qs
|
|
8
|
+
|
|
9
|
+
GO = os.path.expanduser("~/go/bin")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# ---------------------------------------------------------------------------
|
|
13
|
+
def run(cmd, step="", timeout=300, outfile=None):
|
|
14
|
+
print(f"\n[+] {step}" if step else "")
|
|
15
|
+
st = time.time()
|
|
16
|
+
try:
|
|
17
|
+
if outfile:
|
|
18
|
+
with open(outfile, "w") as f:
|
|
19
|
+
p = subprocess.Popen(cmd, shell=True, executable="/bin/bash",
|
|
20
|
+
stdout=f, stderr=subprocess.PIPE, text=True)
|
|
21
|
+
for ln in p.stderr:
|
|
22
|
+
if s := ln.strip():
|
|
23
|
+
print(f" {s}")
|
|
24
|
+
p.wait(timeout=timeout)
|
|
25
|
+
else:
|
|
26
|
+
subprocess.run(cmd, shell=True, executable="/bin/bash",
|
|
27
|
+
timeout=timeout)
|
|
28
|
+
print(f"[v] Done ({round(time.time()-st,1)}s)")
|
|
29
|
+
except subprocess.TimeoutExpired:
|
|
30
|
+
print(f"[x] Timeout after {timeout}s")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# ---------------------------------------------------------------------------
|
|
34
|
+
def extract_params(urls):
|
|
35
|
+
"""Break URLs into endpoint + params + file_type"""
|
|
36
|
+
endpoints, params_map, file_types, post_params, js_files = [], {}, set(), {}, []
|
|
37
|
+
for u in urls:
|
|
38
|
+
u = u.strip()
|
|
39
|
+
if not u or not u.startswith("http"):
|
|
40
|
+
continue
|
|
41
|
+
parsed = urlparse(u)
|
|
42
|
+
path = parsed.path
|
|
43
|
+
|
|
44
|
+
# track JS files separately
|
|
45
|
+
if path.endswith(".js") and "/_next/" not in path:
|
|
46
|
+
js_files.append(u)
|
|
47
|
+
|
|
48
|
+
# detect file types (before filtering)
|
|
49
|
+
if "." in path:
|
|
50
|
+
ext = path.rsplit(".", 1)[-1].lower()
|
|
51
|
+
if ext in ("js","json","xml","yml","env","bak","sql","php","aspx","jsp"):
|
|
52
|
+
file_types.add(ext)
|
|
53
|
+
|
|
54
|
+
# skip static assets and CDN clutter
|
|
55
|
+
if re.search(r"/_next/|/static/|/cdn-cgi/|\.(css|png|jpg|ico|svg|woff|woff2|ttf|map|webp)$", path, re.I):
|
|
56
|
+
continue
|
|
57
|
+
base = f"{parsed.scheme}://{parsed.netloc}{parsed.path}"
|
|
58
|
+
endpoints.append(base)
|
|
59
|
+
|
|
60
|
+
# query params
|
|
61
|
+
qp = parse_qs(parsed.query)
|
|
62
|
+
for k in qp:
|
|
63
|
+
params_map.setdefault(k, []).append(u)
|
|
64
|
+
|
|
65
|
+
# detect POST params from common patterns
|
|
66
|
+
if any(w in u.lower() for w in ["login","signup","register","upload","reset","search"]):
|
|
67
|
+
post_params.setdefault("_suspected_post", []).append(u)
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
"endpoints": sorted(set(endpoints)),
|
|
71
|
+
"params": {k: sorted(set(v)) for k, v in params_map.items()},
|
|
72
|
+
"file_types": sorted(file_types),
|
|
73
|
+
"suspected_post_forms": sorted(set(post_params.get("_suspected_post", []))),
|
|
74
|
+
"js_files": sorted(set(js_files))
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def categorize(endpoints):
|
|
79
|
+
"""Group endpoints by type"""
|
|
80
|
+
cats = {
|
|
81
|
+
"login": [], "api": [], "admin": [], "upload": [],
|
|
82
|
+
"redirect": [], "search": [], "config": [], "other": []
|
|
83
|
+
}
|
|
84
|
+
patterns = {
|
|
85
|
+
"login": r"(login|signin|auth|sso|oauth)",
|
|
86
|
+
"api": r"(/api/|/graphql|/v\d+/|/rest/)",
|
|
87
|
+
"admin": r"(admin|dashboard|panel|wp-admin|cpanel)",
|
|
88
|
+
"upload": r"(upload|import|attachment)",
|
|
89
|
+
"redirect": r"(redirect|callback|return_to|url=|dest=|next=)",
|
|
90
|
+
"search": r"[/?](search|find)[/?]|search\?",
|
|
91
|
+
"config": r"(\.env|\.git|\.bak|config|debug|phpinfo)",
|
|
92
|
+
}
|
|
93
|
+
for ep in endpoints:
|
|
94
|
+
matched = False
|
|
95
|
+
for cat, pat in patterns.items():
|
|
96
|
+
if re.search(pat, ep, re.I):
|
|
97
|
+
cats[cat].append(ep)
|
|
98
|
+
matched = True
|
|
99
|
+
break
|
|
100
|
+
if not matched:
|
|
101
|
+
cats["other"].append(ep)
|
|
102
|
+
return {k: sorted(v) for k, v in cats.items() if v}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def risk_score(ep):
|
|
106
|
+
"""0-10 based on vulnerability surface"""
|
|
107
|
+
# skip static assets
|
|
108
|
+
if re.search(r"/_next/|/static/|\.(css|js|png|jpg|ico|svg|woff|woff2|ttf|map)$", ep, re.I):
|
|
109
|
+
return 0
|
|
110
|
+
score = 1
|
|
111
|
+
if any(w in ep.lower() for w in ["login","auth","admin","dashboard","api","upload"]):
|
|
112
|
+
score += 3
|
|
113
|
+
if "?" in ep:
|
|
114
|
+
score += 2
|
|
115
|
+
if any(w in ep.lower() for w in ["id=","user=","file=","page=","redirect=","url="]):
|
|
116
|
+
score += 3
|
|
117
|
+
return min(score, 10)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
# ---------------------------------------------------------------------------
|
|
121
|
+
def parse_katana_output(url_file):
|
|
122
|
+
"""Katana output format: URL [status] [method] ..."""
|
|
123
|
+
urls, meta = [], []
|
|
124
|
+
with open(url_file, errors="ignore") as f:
|
|
125
|
+
for line in f:
|
|
126
|
+
line = line.strip()
|
|
127
|
+
if not line:
|
|
128
|
+
continue
|
|
129
|
+
urls.append(line.split()[0] if " " in line else line)
|
|
130
|
+
meta.append(line)
|
|
131
|
+
return urls, meta
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# ---------------------------------------------------------------------------
|
|
135
|
+
def parse_whatweb(raw):
|
|
136
|
+
"""Parse whatweb output into tech stack dict"""
|
|
137
|
+
ansi = re.compile(r'\x1b\[[0-9;]*[a-zA-Z]')
|
|
138
|
+
raw_clean = ansi.sub('', raw)
|
|
139
|
+
result = {}
|
|
140
|
+
for line in raw_clean.strip().splitlines():
|
|
141
|
+
# split: URL [status] tag1, tag2[val], ...
|
|
142
|
+
if " [" not in line:
|
|
143
|
+
continue
|
|
144
|
+
# get URL and rest
|
|
145
|
+
parts = line.split(" [", 1)
|
|
146
|
+
url = parts[0].strip()
|
|
147
|
+
rest = parts[1].split("]", 1) # first ] after status code
|
|
148
|
+
if len(rest) < 2:
|
|
149
|
+
continue
|
|
150
|
+
# rest[1] contains all the tags
|
|
151
|
+
tags_raw = rest[1].strip().rstrip(",")
|
|
152
|
+
|
|
153
|
+
# parse tags manually: split on ", " but respect brackets
|
|
154
|
+
tech = {"server": "", "cms": "", "cdn": "", "lang": "", "headers": []}
|
|
155
|
+
current = ""
|
|
156
|
+
depth = 0
|
|
157
|
+
tags = []
|
|
158
|
+
for ch in tags_raw:
|
|
159
|
+
if ch == "[":
|
|
160
|
+
depth += 1
|
|
161
|
+
current += ch
|
|
162
|
+
elif ch == "]":
|
|
163
|
+
depth -= 1
|
|
164
|
+
current += ch
|
|
165
|
+
elif ch == "," and depth == 0:
|
|
166
|
+
tags.append(current.strip())
|
|
167
|
+
current = ""
|
|
168
|
+
else:
|
|
169
|
+
current += ch
|
|
170
|
+
if current.strip():
|
|
171
|
+
tags.append(current.strip())
|
|
172
|
+
|
|
173
|
+
for tag in tags:
|
|
174
|
+
tag = tag.strip()
|
|
175
|
+
if not tag:
|
|
176
|
+
continue
|
|
177
|
+
if "[" in tag:
|
|
178
|
+
key, val = tag.split("[", 1)
|
|
179
|
+
val = val.rstrip("]")
|
|
180
|
+
else:
|
|
181
|
+
key, val = tag, ""
|
|
182
|
+
|
|
183
|
+
k = key.lower()
|
|
184
|
+
if "httpserver" in k:
|
|
185
|
+
tech["server"] = val
|
|
186
|
+
elif "x-powered-by" in k:
|
|
187
|
+
tech["cms"] = val
|
|
188
|
+
elif k in ("cloudflare", "cloudfront"):
|
|
189
|
+
tech["cdn"] = key
|
|
190
|
+
elif k in ("next.js", "php", "asp_net", "laravel", "django", "ruby"):
|
|
191
|
+
tech["lang"] = val or key
|
|
192
|
+
elif any(h in k for h in ("x-", "strict-transport", "content-security")):
|
|
193
|
+
tech["headers"].append(key)
|
|
194
|
+
|
|
195
|
+
result[url] = {k: v for k, v in tech.items() if v}
|
|
196
|
+
if "server" not in result[url] and "cms" not in result[url]:
|
|
197
|
+
result[url]["server"] = "unknown"
|
|
198
|
+
return result
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def scan_tech(alive_file, outdir):
|
|
202
|
+
"""Use whatweb to detect tech stack"""
|
|
203
|
+
if not os.path.exists(alive_file):
|
|
204
|
+
return {}
|
|
205
|
+
hosts = [l.strip() for l in open(alive_file) if l.strip().startswith("http")]
|
|
206
|
+
if not hosts:
|
|
207
|
+
return {}
|
|
208
|
+
print("\n[*] WhatWeb (tech detection)...")
|
|
209
|
+
outfile = f"{outdir}/whatweb.txt"
|
|
210
|
+
cmd = f"whatweb --color=never --no-errors {' '.join(hosts)} > {outfile}"
|
|
211
|
+
run(cmd, f"WhatWeb ({len(hosts)} hosts)")
|
|
212
|
+
if os.path.exists(outfile):
|
|
213
|
+
return parse_whatweb(open(outfile).read())
|
|
214
|
+
return {}
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
# ---------------------------------------------------------------------------
|
|
218
|
+
def build_ai_report(target, d):
|
|
219
|
+
report = {"target": target, "scan_date": time.strftime("%Y-%m-%d %H:%M")}
|
|
220
|
+
|
|
221
|
+
# --- subdomains + alive ---
|
|
222
|
+
subs = open(f"{d}/subdomains.txt","r").read().splitlines() if os.path.exists(f"{d}/subdomains.txt") else []
|
|
223
|
+
alive = []
|
|
224
|
+
if os.path.exists(f"{d}/alive.txt"):
|
|
225
|
+
for ln in open(f"{d}/alive.txt"):
|
|
226
|
+
ln = ln.strip()
|
|
227
|
+
if ln.startswith("http"):
|
|
228
|
+
alive.append({"url": ln, "status": "alive"})
|
|
229
|
+
|
|
230
|
+
# --- katana output ---
|
|
231
|
+
raw_urls, _ = parse_katana_output(f"{d}/urls.txt") if os.path.exists(f"{d}/urls.txt") else ([], [])
|
|
232
|
+
ep_info = extract_params(raw_urls)
|
|
233
|
+
cat = categorize(ep_info["endpoints"])
|
|
234
|
+
|
|
235
|
+
# risk scoring
|
|
236
|
+
risky = sorted([e for e in ep_info["endpoints"] if risk_score(e) > 0],
|
|
237
|
+
key=lambda x: -risk_score(x))[:20]
|
|
238
|
+
|
|
239
|
+
# --- whatweb tech stack ---
|
|
240
|
+
tech_stack = scan_tech(f"{d}/alive.txt", d)
|
|
241
|
+
|
|
242
|
+
# --- gf patterns ---
|
|
243
|
+
gf_data = {}
|
|
244
|
+
for name in ["xss","sqli","idor"]:
|
|
245
|
+
fp = f"{d}/{name}.txt"
|
|
246
|
+
if os.path.exists(fp):
|
|
247
|
+
gf_data[name] = [l.strip() for l in open(fp) if l.strip()][:30]
|
|
248
|
+
|
|
249
|
+
# --- assemble ---
|
|
250
|
+
report["summary"] = {
|
|
251
|
+
"subdomains": len(subs),
|
|
252
|
+
"alive_hosts": len(alive),
|
|
253
|
+
"endpoints": len(ep_info["endpoints"]),
|
|
254
|
+
"params_with_input": list(ep_info["params"].keys()),
|
|
255
|
+
"file_types": ep_info["file_types"],
|
|
256
|
+
"tech_detected": {u: t.get("cms") or t.get("cdn") or t.get("server") or "unknown" for u, t in tech_stack.items()},
|
|
257
|
+
"gf_matches": {k: len(v) for k, v in gf_data.items()},
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
report["subdomains"] = subs
|
|
261
|
+
report["alive_hosts"] = alive
|
|
262
|
+
|
|
263
|
+
report["attack_surface"] = {
|
|
264
|
+
"tech_stack": tech_stack,
|
|
265
|
+
"by_category": cat,
|
|
266
|
+
"top_risky_endpoints": [{"url": u, "score": risk_score(u)} for u in risky],
|
|
267
|
+
"query_params": ep_info["params"],
|
|
268
|
+
"suspected_post_forms": ep_info["suspected_post_forms"],
|
|
269
|
+
"interesting_files": ep_info["file_types"],
|
|
270
|
+
"js_files": ep_info["js_files"][:30],
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
report["vulnerabilities"] = {
|
|
274
|
+
"gf_pattern_matches": gf_data,
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
report["suggestions"] = generate_suggestions(report, target)
|
|
278
|
+
|
|
279
|
+
with open(f"{d}/ai_ready.json", "w") as f:
|
|
280
|
+
json.dump(report, f, indent=2, ensure_ascii=False)
|
|
281
|
+
|
|
282
|
+
print(f"\n[+] AI Report saved: {d}/ai_ready.json")
|
|
283
|
+
print_summary(report)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def generate_suggestions(r, t):
|
|
287
|
+
s = []
|
|
288
|
+
ps = r["attack_surface"]["query_params"]
|
|
289
|
+
cat = r["attack_surface"]["by_category"]
|
|
290
|
+
|
|
291
|
+
if cat.get("login"):
|
|
292
|
+
s.append("Brute-force / default creds on login endpoints")
|
|
293
|
+
if cat.get("api"):
|
|
294
|
+
s.append("Test API endpoints for auth bypass, IDOR, rate-limit")
|
|
295
|
+
if cat.get("upload"):
|
|
296
|
+
s.append("Test file upload for RCE, XSS, unrestricted upload")
|
|
297
|
+
if cat.get("redirect"):
|
|
298
|
+
s.append("Check for open redirect via redirect parameters")
|
|
299
|
+
if cat.get("search"):
|
|
300
|
+
s.append("Test search endpoints for reflected XSS")
|
|
301
|
+
if cat.get("admin"):
|
|
302
|
+
s.append("Check admin access controls, try /admin, /wp-admin")
|
|
303
|
+
if any(k in ps for k in ["id","user","uid","order","pid"]):
|
|
304
|
+
s.append("IDOR: try incrementing/decrementing id parameters")
|
|
305
|
+
if any(k in ps for k in ["q","s","query","search","keyword"]):
|
|
306
|
+
s.append("XSS: inject <script>alert(1)</script> in search/query params")
|
|
307
|
+
if any(k in ps for k in ["redirect","url","return","next","dest"]):
|
|
308
|
+
s.append("Open redirect: try //evil.com in redirect params")
|
|
309
|
+
if any(k in ps for k in ["file","path","include","template"]):
|
|
310
|
+
s.append("LFI/Path Traversal: try ../../etc/passwd in file params")
|
|
311
|
+
if r["attack_surface"]["js_files"]:
|
|
312
|
+
s.append("Check JS files for hidden endpoints, API keys, secrets")
|
|
313
|
+
if "bak" in r["attack_surface"]["interesting_files"] or ".env" in str(r["attack_surface"]):
|
|
314
|
+
s.append("Check backup/config files for exposed credentials")
|
|
315
|
+
if any(w in str(r["subdomains"]).lower() for w in ["dev","staging","test","beta","uat"]):
|
|
316
|
+
s.append("Dev/Staging environments often have weaker security")
|
|
317
|
+
|
|
318
|
+
# tech-specific suggestions
|
|
319
|
+
ts = r["attack_surface"]["tech_stack"]
|
|
320
|
+
for host, info in ts.items():
|
|
321
|
+
cms = info.get("cms","").lower()
|
|
322
|
+
svr = info.get("server","").lower()
|
|
323
|
+
if "next.js" in cms or "next.js" in info.get("lang","").lower():
|
|
324
|
+
s.append(f"{host}: Next.js — check /api/, /_next/, source maps, SSR params")
|
|
325
|
+
if "wordpress" in cms:
|
|
326
|
+
s.append(f"{host}: WordPress — check /wp-json/, /wp-admin/, xmlrpc.php")
|
|
327
|
+
if "php" in cms or "php" in svr or "php" in info.get("lang",""):
|
|
328
|
+
s.append(f"{host}: PHP detected — test for LFI, PHPInfo, file upload bypass")
|
|
329
|
+
|
|
330
|
+
return s if s else ["Analyze all endpoints for common OWASP Top 10 vulnerabilities"]
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def print_summary(r):
|
|
334
|
+
s = r["summary"]
|
|
335
|
+
print("\n" + "=" * 55)
|
|
336
|
+
print(f" Target: {r['target']}")
|
|
337
|
+
print(f" Subdomains: {s['subdomains']} | Alive: {s['alive_hosts']} | Endpoints: {s['endpoints']}")
|
|
338
|
+
print(f" Params: {s['params_with_input']}")
|
|
339
|
+
print(f" File types: {s['file_types']}")
|
|
340
|
+
print(f" Tech: {s.get('tech_detected', {})}")
|
|
341
|
+
print(f" GF matches: {s['gf_matches']}")
|
|
342
|
+
print(f" Suggestions: {len(r['suggestions'])} tips")
|
|
343
|
+
print("=" * 55)
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
# ---------------------------------------------------------------------------
|
|
347
|
+
def main():
|
|
348
|
+
print("=" * 55)
|
|
349
|
+
print(" Auto Recon -> AI Ready")
|
|
350
|
+
print("=" * 55)
|
|
351
|
+
|
|
352
|
+
target = input("\n[>] Domain: ").strip()
|
|
353
|
+
if not target:
|
|
354
|
+
return
|
|
355
|
+
|
|
356
|
+
# clean input: strip https://, http://, trailing /
|
|
357
|
+
target = re.sub(r'^https?://', '', target).rstrip('/')
|
|
358
|
+
|
|
359
|
+
d = f"recon_{target}"
|
|
360
|
+
os.makedirs(d, exist_ok=True)
|
|
361
|
+
start = time.time()
|
|
362
|
+
|
|
363
|
+
# Phase 1 — subfinder + httpx
|
|
364
|
+
run(
|
|
365
|
+
f"{GO}/subfinder -d {target} -s hackertarget,waybackarchive -silent | "
|
|
366
|
+
f"tee {d}/subdomains.txt | "
|
|
367
|
+
f"httpx-toolkit -mc 200,301,403 -silent > {d}/alive.txt",
|
|
368
|
+
"Subfinder + Httpx"
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
# Phase 2 — whatweb + katana (parallel)
|
|
372
|
+
print("\n[*] WhatWeb + Katana (parallel)...")
|
|
373
|
+
# whatweb is already called inside build_ai_report via scan_tech()
|
|
374
|
+
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as ex:
|
|
375
|
+
f1 = ex.submit(run, f"{GO}/katana -list {d}/alive.txt -d 3 -c 15 -silent > {d}/urls.txt",
|
|
376
|
+
"Katana (crawl)")
|
|
377
|
+
concurrent.futures.wait([f1])
|
|
378
|
+
|
|
379
|
+
# Phase 3 — gf patterns
|
|
380
|
+
if os.path.exists(f"{d}/urls.txt"):
|
|
381
|
+
run(
|
|
382
|
+
f"cat {d}/urls.txt | {GO}/gf xss > {d}/xss.txt && "
|
|
383
|
+
f"cat {d}/urls.txt | {GO}/gf sqli > {d}/sqli.txt && "
|
|
384
|
+
f"cat {d}/urls.txt | {GO}/gf idor > {d}/idor.txt",
|
|
385
|
+
"gf (XSS/SQLi/IDOR patterns)"
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
# Phase 4 — build AI report
|
|
389
|
+
build_ai_report(target, d)
|
|
390
|
+
|
|
391
|
+
print(f"\n[√] Total: {round(time.time()-start,1)}s")
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
if __name__ == "__main__":
|
|
395
|
+
main()
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hb-recon
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Automated reconnaissance tool with AI report generation. Subdomain enumeration, endpoint crawling, and vulnerability pattern detection.
|
|
5
|
+
Author-email: Hlaing Bwar <infohlaingbwar@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/infohlaingbwar/hb-recon
|
|
8
|
+
Project-URL: Repository, https://github.com/infohlaingbwar/hb-recon
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/infohlaingbwar/hb-recon/issues
|
|
10
|
+
Keywords: recon,reconnaissance,osint,bug-bounty,pentesting,subdomain,enumeration,security,ethical-hacking
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Intended Audience :: Information Technology
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Security
|
|
22
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
23
|
+
Classifier: Operating System :: MacOS
|
|
24
|
+
Requires-Python: >=3.8
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
29
|
+
Requires-Dist: black>=22.0; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# HB-Recon
|
|
33
|
+
|
|
34
|
+
**Automated reconnaissance tool with AI-ready report generation.**
|
|
35
|
+
|
|
36
|
+
Perfect for bug bounty hunters, pentesters, and security researchers.
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
✅ **Subdomain Enumeration** — subfinder integration
|
|
41
|
+
✅ **Live Host Detection** — httpx for alive checks
|
|
42
|
+
✅ **Technology Stack Scan** — WhatWeb detection
|
|
43
|
+
✅ **Endpoint Crawling** — Katana deep crawl
|
|
44
|
+
✅ **Vulnerability Patterns** — gf (XSS, SQLi, IDOR detection)
|
|
45
|
+
✅ **AI Report Generation** — Structured JSON output
|
|
46
|
+
|
|
47
|
+
## Requirements
|
|
48
|
+
|
|
49
|
+
**External Tools (must be installed):**
|
|
50
|
+
- [subfinder](https://github.com/projectdiscovery/subfinder)
|
|
51
|
+
- [httpx](https://github.com/projectdiscovery/httpx)
|
|
52
|
+
- [katana](https://github.com/projectdiscovery/katana)
|
|
53
|
+
- [gf](https://github.com/tomnomnom/gf)
|
|
54
|
+
- [whatweb](https://github.com/urbanadventurer/WhatWeb)
|
|
55
|
+
|
|
56
|
+
**Install tools:**
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
## Install
|
|
60
|
+
|
|
61
|
+
Defaulting to user installation because normal site-packages is not writeable
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
**Example:**
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
**Output Structure:**
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
## AI Report
|
|
74
|
+
|
|
75
|
+
The tool generates with:
|
|
76
|
+
- Target info
|
|
77
|
+
- Discovered subdomains & endpoints
|
|
78
|
+
- Technology stack
|
|
79
|
+
- Risk-scored vulnerabilities
|
|
80
|
+
- Attack surface summary
|
|
81
|
+
|
|
82
|
+
Perfect for feeding into AI tools like ChatGPT, Claude for analysis.
|
|
83
|
+
|
|
84
|
+
## Example Workflow
|
|
85
|
+
|
|
86
|
+
Defaulting to user installation because normal site-packages is not writeable
|
|
87
|
+
|
|
88
|
+
## Security Notice
|
|
89
|
+
|
|
90
|
+
⚠️ **Only use on authorized targets.** Unauthorized scanning is illegal.
|
|
91
|
+
|
|
92
|
+
## License
|
|
93
|
+
|
|
94
|
+
MIT License - See [LICENSE](LICENSE)
|
|
95
|
+
|
|
96
|
+
## Author
|
|
97
|
+
|
|
98
|
+
**Hlaing Bwar**
|
|
99
|
+
- GitHub: [@infohlaingbwar](https://github.com/infohlaingbwar)
|
|
100
|
+
- Website: [hlaingbwar.com](https://www.hlaingbwar.com)
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
**Made with ❤️ for the bug bounty community**
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
hb_recon/__init__.py
|
|
5
|
+
hb_recon/__main__.py
|
|
6
|
+
hb_recon/cli.py
|
|
7
|
+
hb_recon.egg-info/PKG-INFO
|
|
8
|
+
hb_recon.egg-info/SOURCES.txt
|
|
9
|
+
hb_recon.egg-info/dependency_links.txt
|
|
10
|
+
hb_recon.egg-info/entry_points.txt
|
|
11
|
+
hb_recon.egg-info/requires.txt
|
|
12
|
+
hb_recon.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
hb_recon
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "hb-recon"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Automated reconnaissance tool with AI report generation. Subdomain enumeration, endpoint crawling, and vulnerability pattern detection."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Hlaing Bwar", email = "infohlaingbwar@gmail.com"}
|
|
14
|
+
]
|
|
15
|
+
keywords = ["recon", "reconnaissance", "osint", "bug-bounty", "pentesting", "subdomain", "enumeration", "security", "ethical-hacking"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 5 - Production/Stable",
|
|
18
|
+
"Intended Audience :: Information Technology",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.8",
|
|
23
|
+
"Programming Language :: Python :: 3.9",
|
|
24
|
+
"Programming Language :: Python :: 3.10",
|
|
25
|
+
"Programming Language :: Python :: 3.11",
|
|
26
|
+
"Programming Language :: Python :: 3.12",
|
|
27
|
+
"Topic :: Security",
|
|
28
|
+
"Operating System :: POSIX :: Linux",
|
|
29
|
+
"Operating System :: MacOS",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
dependencies = []
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
dev = [
|
|
36
|
+
"pytest>=7.0",
|
|
37
|
+
"black>=22.0",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[project.urls]
|
|
41
|
+
Homepage = "https://github.com/infohlaingbwar/hb-recon"
|
|
42
|
+
Repository = "https://github.com/infohlaingbwar/hb-recon"
|
|
43
|
+
"Bug Tracker" = "https://github.com/infohlaingbwar/hb-recon/issues"
|
|
44
|
+
|
|
45
|
+
[project.scripts]
|
|
46
|
+
hb-recon = "hb_recon.cli:main"
|
|
47
|
+
|
|
48
|
+
[tool.setuptools.packages.find]
|
|
49
|
+
where = ["."]
|
|
50
|
+
include = ["hb_recon*"]
|
|
51
|
+
exclude = ["tests*", "docs*"]
|
hb_recon-1.0.0/setup.cfg
ADDED