mirror of
https://github.com/0xMarcio/PentestPilot.git
synced 2026-06-08 07:13:53 +02:00
461c14d676
Initial commit of PentestPilot — AI‑assisted pentest recon and orchestration toolkit.\n\nHighlights:\n- Resumeable pipelines (full_pipeline) with manifest state and elapsed timings\n- Rich dashboard (colors, severity bars, durations, compact/json modes)\n- Web helpers: httpx→nuclei auto, tech routing + quick scanners\n- Agents: multi‑task orchestrator (web/full/ad/notes/post) with resume\n- AD/SMB, password utils, shells, transfer, privesc, tunnels\n- QoL scripts: proxy toggle, cleanup, tmux init, URL extractor\n- Docs: README (Quick Start + Docs Index), HOWTO (deep guide), TOOLKIT (catalog with examples)\n\nStructure:\n- bin/automation: pipelines, dashboard, manifest, resume, tech_actions\n- bin/web: routing, scanners, helpers\n- bin/ai: orchestrators + robust AI utils\n- bin/ad, bin/passwords, bin/shells, bin/transfer, bin/privesc, bin/misc, bin/dns, bin/scan, bin/windows, bin/hashes\n- HOWTO.md and TOOLKIT.md cross‑linked with examples\n\nUse:\n- settarget <target>; agent full <domain|hosts.txt>; dashboard --compact\n- See HOWTO.md for setup, semantics, and examples.
95 lines
4.1 KiB
Python
Executable File
95 lines
4.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import os, sys, json
|
|
|
|
HELP = """Usage: tech_actions.py <target> [--run]
|
|
Reads targets/<target>/manifest.json, looks at httpx_summary techs, and prints suggested next-step commands.
|
|
With --run, executes the suggestions sequentially (best-effort).
|
|
"""
|
|
|
|
def load_manifest(root, target):
|
|
path=os.path.join(root,'targets',target,'manifest.json')
|
|
try:
|
|
with open(path,'r') as f:
|
|
return json.load(f)
|
|
except Exception:
|
|
return {}
|
|
|
|
if len(sys.argv) < 2:
|
|
print(HELP, file=sys.stderr); sys.exit(1)
|
|
|
|
target=sys.argv[1]
|
|
run=('--run' in sys.argv)
|
|
root=os.environ.get('HTB_ROOT', os.getcwd())
|
|
outdir=os.environ.get('OUTDIR', os.path.join(root,'targets',target,'scans'))
|
|
data=load_manifest(root, target)
|
|
tasks=(data.get('tasks') or {})
|
|
httpx_meta=(tasks.get('httpx') or {}).get('meta') or {}
|
|
nuclei_meta=(tasks.get('nuclei') or {}).get('meta') or {}
|
|
summary_path=httpx_meta.get('httpx_summary')
|
|
if not summary_path or not os.path.isfile(summary_path):
|
|
print(f"[!] No httpx_summary found for {target}", file=sys.stderr); sys.exit(2)
|
|
|
|
summary=json.load(open(summary_path))
|
|
tech=summary.get('tech') or {}
|
|
if not tech:
|
|
print(f"[!] No technologies found in summary", file=sys.stderr); sys.exit(3)
|
|
|
|
def suggest_for(tech):
|
|
m={
|
|
'wordpress': [f"bin/web/httpx_tech_route.py {data.get('tasks').get('httpx',{}).get('meta',{}).get('urls_file','urls.txt')} --tech wordpress --severity medium,high,critical --wpscan --wpscan-limit 5"],
|
|
'drupal': ["bin/web/droopescan_quick.sh URL"],
|
|
'joomla': ["bin/web/joomscan_quick.sh URL"],
|
|
'jenkins': ["bin/web/jenkins_quick.sh URL"],
|
|
'sonarqube': ["bin/web/sonarqube_quick.sh URL"],
|
|
'magento': ["bin/web/magento_quick.sh URL"],
|
|
'jira': ["bin/web/jira_quick.sh URL"],
|
|
'confluence': ["bin/web/confluence_quick.sh URL"],
|
|
'gitlab': ["bin/web/httpx_tech_route.py URLS --tech gitlab"],
|
|
'grafana': ["bin/web/httpx_tech_route.py URLS --tech grafana"],
|
|
'kibana': ["bin/web/httpx_tech_route.py URLS --tech kibana"],
|
|
'exchange': ["bin/web/httpx_tech_route.py URLS --tech exchange"],
|
|
'sharepoint': ["bin/web/httpx_tech_route.py URLS --tech sharepoint"],
|
|
}
|
|
return m.get(tech, [f"bin/web/httpx_tech_route.py URLS --tech {tech}"])
|
|
|
|
print(f"[+] Target: {target}")
|
|
urls_file=httpx_meta.get('urls_file','')
|
|
top=sorted(tech.items(), key=lambda x: x[1], reverse=True)
|
|
for name,count in top[:8]:
|
|
print(f"\n# {name} ({count})")
|
|
for cmd in suggest_for(name):
|
|
c=cmd.replace('URLS', urls_file).replace('URL', '<url>')
|
|
print(c)
|
|
if run and ' <url>' not in c:
|
|
os.system(c)
|
|
|
|
# Findings-based suggestions (safe-only)
|
|
nj=nuclei_meta.get('nuclei_json')
|
|
if nj and os.path.isfile(nj):
|
|
sev_order={'critical':0,'high':1,'medium':2,'low':3}
|
|
tags_index={}
|
|
with open(nj,'r',errors='ignore') as f:
|
|
for line in f:
|
|
try:
|
|
o=json.loads(line)
|
|
sev=(o.get('info') or {}).get('severity','').lower()
|
|
if sev not in ('critical','high'): continue
|
|
tags=(o.get('info') or {}).get('tags','')
|
|
for t in (tags.split(',') if isinstance(tags,str) else []):
|
|
t=t.strip().lower();
|
|
if not t: continue
|
|
tags_index.setdefault(t,0); tags_index[t]+=1
|
|
except Exception:
|
|
pass
|
|
if tags_index:
|
|
print("\n# Findings-based next steps (high/critical)")
|
|
for t,cnt in sorted(tags_index.items(), key=lambda x: -x[1])[:10]:
|
|
if t in ('wordpress','wp'): print(f"bin/web/httpx_tech_route.py {urls_file} --tech wordpress --wpscan --wpscan-limit 5")
|
|
elif t in ('jenkins',): print("bin/web/jenkins_quick.sh <url>")
|
|
elif t in ('confluence',): print("bin/web/confluence_quick.sh <url>")
|
|
elif t in ('jira',): print("bin/web/jira_quick.sh <url>")
|
|
elif t in ('drupal',): print("bin/web/droopescan_quick.sh <url>")
|
|
elif t in ('joomla',): print("bin/web/joomscan_quick.sh <url>")
|
|
else:
|
|
print(f"bin/web/httpx_tech_route.py {urls_file} --tech {t}")
|