The Analyzer v2.0 — 30 attack vectors, 9 new exploiters
New vectors added: - 22: SSRF Proof — cloud metadata exfiltration (CRITICAL) - 23: Prototype Pollution — Node.js client/server (HIGH) - 24: WebSocket Hijack — WS origin bypass + injection (HIGH) - 25: Mass Assignment — protected field modification (HIGH) - 26: HTTP Parameter Pollution — WAF bypass (HIGH) - 27: Insecure Deserialization — PHP/Java/Node (CRITICAL) - 28: OAuth Takeover — redirect_uri / state / CSRF (CRITICAL) - 29: Web Cache Poisoning — unkeyed header injection (HIGH) - 30: CRLF Injection — HTTP response splitting (CRITICAL) All vectors PROVE exploitation by dumping data/credentials, not just detecting config issues.
This commit is contained in:
280
engine/autobounty.py
Normal file
280
engine/autobounty.py
Normal file
@@ -0,0 +1,280 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
AutoBounty — Autonomous Bug Bounty Pipeline
|
||||
Discovers subdomains → tech-detect → CVE scan → The Analyzer exploit
|
||||
No API keys needed (Shodan DNS is free tier)
|
||||
"""
|
||||
import subprocess, json, sys, os, time
|
||||
from pathlib import Path
|
||||
from collections import Counter
|
||||
|
||||
ANALYZER_DIR = os.path.expanduser("~/the-analyzer")
|
||||
REPORTS_DIR = f"{ANALYZER_DIR}/reports"
|
||||
HTTPX = os.path.expanduser("~/go/bin/httpx")
|
||||
NUCLEI_TEMPLATES = os.path.expanduser("~/nuclei-templates")
|
||||
SHODAN_KEY = "8IPLCrASad9cLHqo6xwzGNxOPcldnGDG"
|
||||
|
||||
os.makedirs(f"{ANALYZER_DIR}/targets", exist_ok=True)
|
||||
|
||||
def log(msg): print(f"\033[94m[*]\033[0m {msg}")
|
||||
def ok(msg): print(f"\033[92m[✓]\033[0m {msg}")
|
||||
def bad(msg): print(f"\033[91m[✗]\033[0m {msg}")
|
||||
|
||||
def run(cmd, timeout=120):
|
||||
try:
|
||||
r = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=timeout)
|
||||
return r.stdout, r.stderr, r.returncode
|
||||
except subprocess.TimeoutExpired:
|
||||
return "", "TIMEOUT", 124
|
||||
|
||||
def shodan_subdomains(domain):
|
||||
"""Enumerate subdomains using free Shodan DNS API"""
|
||||
log(f"Enumerating subdomains for {domain}...")
|
||||
try:
|
||||
import urllib.request, json, ssl
|
||||
ctx = ssl.create_default_context()
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
url = f"https://api.shodan.io/dns/domain/{domain}?key={SHODAN_KEY}"
|
||||
r = urllib.request.urlopen(url, context=ctx, timeout=10)
|
||||
data = json.loads(r.read().decode())
|
||||
|
||||
subdomains = data.get("subdomains", [])
|
||||
results = []
|
||||
for sd in subdomains:
|
||||
fqdn = f"{sd}.{domain}"
|
||||
# Filter out wildcard/mass-provisioned subdomains
|
||||
if not any(x in sd for x in ["clients6", "prod-dynamite", "preprod-dynamite", "client-channel"]):
|
||||
results.append(fqdn)
|
||||
|
||||
if results:
|
||||
ok(f"Found {len(results)} subdomains")
|
||||
return results
|
||||
else:
|
||||
log(f"No clean subdomains found")
|
||||
return []
|
||||
except Exception as e:
|
||||
bad(f"Shodan DNS error: {e}")
|
||||
return []
|
||||
|
||||
def probe_targets(domains, output_file):
|
||||
"""Probe targets with httpx tech detection"""
|
||||
if not domains:
|
||||
return None
|
||||
|
||||
# Write targets
|
||||
target_file = "/tmp/autobounty_targets.txt"
|
||||
with open(target_file, "w") as f:
|
||||
f.write("\n".join(domains))
|
||||
|
||||
log(f"Probing {len(domains)} targets with tech detection...")
|
||||
stdout, stderr, rc = run(
|
||||
f"cat {target_file} | {HTTPX} -rl 20 -timeout 5 -tech-detect -j -o {output_file} -silent 2>/dev/null",
|
||||
timeout=180
|
||||
)
|
||||
|
||||
count = 0
|
||||
if os.path.exists(output_file):
|
||||
with open(output_file) as f:
|
||||
count = sum(1 for _ in f)
|
||||
ok(f"{count} live hosts detected")
|
||||
return output_file
|
||||
|
||||
def run_cve_scan(targets_file, severity="all"):
|
||||
"""Run targeted CVE scan on live targets"""
|
||||
if not targets_file or not os.path.exists(targets_file):
|
||||
return None, 0
|
||||
|
||||
# Extract just URLs
|
||||
url_file = "/tmp/autobounty_urls.txt"
|
||||
run(f"python3 -c 'import json; [print(json.loads(l).get(\"url\",\"\")) for l in open(\"{targets_file}\") if l.strip()]' > {url_file}")
|
||||
|
||||
live_count = 0
|
||||
with open(url_file) as f:
|
||||
live_count = sum(1 for _ in f)
|
||||
|
||||
if live_count == 0:
|
||||
return None, 0
|
||||
|
||||
log(f"Running CVE scan on {live_count} live hosts...")
|
||||
|
||||
findings_file = f"{REPORTS_DIR}/autobounty_cve_{int(time.time())}.json"
|
||||
|
||||
if severity == "all":
|
||||
stdout, stderr, rc = run(
|
||||
f"nuclei -l {url_file} -j -rl 15 -c 8 "
|
||||
f"-t {NUCLEI_TEMPLATES}/http/cves/ "
|
||||
f"-severity critical,high,medium "
|
||||
f"-o {findings_file} "
|
||||
f"-silent 2>/dev/null",
|
||||
timeout=180
|
||||
)
|
||||
else:
|
||||
stdout, stderr, rc = run(
|
||||
f"nuclei -l {url_file} -j -rl 15 -c 8 "
|
||||
f"-t {NUCLEI_TEMPLATES}/http/cves/ "
|
||||
f"-severity critical,high "
|
||||
f"-o {findings_file} "
|
||||
f"-silent 2>/dev/null",
|
||||
timeout=120
|
||||
)
|
||||
|
||||
count = 0
|
||||
if os.path.exists(findings_file):
|
||||
with open(findings_file) as f:
|
||||
count = sum(1 for l in f if l.strip())
|
||||
|
||||
return findings_file, count
|
||||
|
||||
def print_tech_summary(tech_file):
|
||||
"""Print technology summary"""
|
||||
techs = Counter()
|
||||
with open(tech_file) as f:
|
||||
for line in f:
|
||||
try:
|
||||
d = json.loads(line)
|
||||
url = d.get("url", "")
|
||||
for t in d.get("tech", []):
|
||||
techs[t] += 1
|
||||
print(f" {url:60} {', '.join(d.get('tech', ['-']))}")
|
||||
except: pass
|
||||
|
||||
if techs:
|
||||
print(f"\n Technology breakdown:")
|
||||
for tech, cnt in techs.most_common(10):
|
||||
print(f" {tech:35} {cnt} targets")
|
||||
|
||||
def print_findings(findings_file):
|
||||
"""Print CVE findings in readable format"""
|
||||
if not findings_file or not os.path.exists(findings_file):
|
||||
return
|
||||
|
||||
findings = []
|
||||
with open(findings_file) as f:
|
||||
for line in f:
|
||||
if not line.strip(): continue
|
||||
try:
|
||||
d = json.loads(line)
|
||||
cve = "N/A"
|
||||
for ref in d.get("info", {}).get("classification", {}).get("cve", []):
|
||||
cve = ref.get("id", "N/A")
|
||||
break
|
||||
findings.append({
|
||||
"url": d.get("matched-at", "?"),
|
||||
"cve": cve,
|
||||
"severity": d.get("info", {}).get("severity", "?"),
|
||||
"name": d.get("info", {}).get("name", "?"),
|
||||
"template": d.get("template-id", ""),
|
||||
})
|
||||
except: pass
|
||||
|
||||
if findings:
|
||||
icons = {"critical": "🔴", "high": "🟠", "medium": "🟡"}
|
||||
print(f"\n CVEs found:")
|
||||
for f_data in findings:
|
||||
icon = icons.get(f_data["severity"], "⚪")
|
||||
print(f" {icon} {f_data['cve']:20} {f_data['name'][:60]}")
|
||||
print(f" {f_data['url']}")
|
||||
|
||||
# ============================================================
|
||||
# MAIN — Hunt a specific target domain
|
||||
# ============================================================
|
||||
|
||||
def hunt_target(domain):
|
||||
"""Full pipeline for a single target domain"""
|
||||
print()
|
||||
print(f"╔═══════════════════════════════════════════╗")
|
||||
print(f"║ AUTOBOUNTY — {domain:40}║")
|
||||
print(f"╚═══════════════════════════════════════════╝")
|
||||
print()
|
||||
|
||||
# Phase 1: Subdomain enumeration
|
||||
log("Phase 1: Subdomain enumeration")
|
||||
subdomains = shodan_subdomains(domain)
|
||||
|
||||
all_targets = [domain] + (subdomains if subdomains else [])
|
||||
|
||||
if not all_targets:
|
||||
bad("No targets to scan")
|
||||
return
|
||||
|
||||
ok(f"Total targets: {len(all_targets)}")
|
||||
|
||||
# Phase 2: Tech detection
|
||||
print()
|
||||
log("Phase 2: Tech detection")
|
||||
tech_file = f"/tmp/autobounty_tech_{domain.replace('.', '_')}.json"
|
||||
tech_file = probe_targets(all_targets, tech_file)
|
||||
|
||||
if not tech_file:
|
||||
bad("No live hosts found")
|
||||
return
|
||||
|
||||
print()
|
||||
print_tech_summary(tech_file)
|
||||
|
||||
# Phase 3: CVE scan
|
||||
print()
|
||||
log("Phase 3: CVE scanning")
|
||||
findings_file, count = run_cve_scan(tech_file)
|
||||
|
||||
print()
|
||||
if count > 0:
|
||||
ok(f"Found {count} CVEs!")
|
||||
print_findings(findings_file)
|
||||
else:
|
||||
log("No CVEs detected on these subdomains")
|
||||
|
||||
# Phase 4: The Analyzer exploit
|
||||
if count > 0 and findings_file:
|
||||
print()
|
||||
log("Phase 4: Ready for deep exploitation")
|
||||
log("Run: ./analyzer <vulnerable-url> deep")
|
||||
|
||||
print()
|
||||
print("=" * 60)
|
||||
print(f" Target: {domain}")
|
||||
print(f" Subdomains: {len(subdomains) if subdomains else 0}")
|
||||
print(f" Live: {sum(1 for _ in open(tech_file)) if os.path.exists(tech_file) else 0}")
|
||||
print(f" CVEs: {count}")
|
||||
print("=" * 60)
|
||||
|
||||
# ============================================================
|
||||
# CONTINUOUS SCAN (cron-ready)
|
||||
# ============================================================
|
||||
|
||||
def scan_known_targets():
|
||||
"""Scan all known bug bounty targets for new subdomains"""
|
||||
targets = [
|
||||
"google.com", "facebook.com", "twitter.com", "instagram.com",
|
||||
"github.com", "gitlab.com", "atlassian.com", "slack.com",
|
||||
"shopify.com", "stripe.com", "paypal.com", "discord.com",
|
||||
"reddit.com", "twitch.com", "spotify.com", "cloudflare.com",
|
||||
"digitalocean.com", "magento.com", "salesforce.com", "hubspot.com",
|
||||
]
|
||||
|
||||
for target in targets:
|
||||
print(f"\n{'='*60}")
|
||||
hunt_target(target)
|
||||
|
||||
def print_usage():
|
||||
print("Usage:")
|
||||
print(" python3 autobounty.py <domain> # Hunt a specific target")
|
||||
print(" python3 autobounty.py all # Scan all known targets")
|
||||
print(" python3 autobounty.py watch <domain> # Setup daily cron scan")
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print_usage()
|
||||
sys.exit(1)
|
||||
|
||||
mode = sys.argv[1]
|
||||
|
||||
if mode == "all":
|
||||
scan_known_targets()
|
||||
elif mode == "watch" and len(sys.argv) >= 3:
|
||||
domain = sys.argv[2]
|
||||
print(f"Would setup cron for daily scan of {domain}")
|
||||
hunt_target(domain)
|
||||
else:
|
||||
hunt_target(mode)
|
||||
Reference in New Issue
Block a user