Files
T
mukul975 c47eed6a64 Production hardening: security fixes, code quality, 724 skills complete
- Fix 25 shell=True subprocess calls with list-based commands
- Fix 49 verify=False in defensive skills (env-var override)
- Add timeout to 231 HTTP/subprocess/socket calls
- Fix 6 SQL injection patterns with whitelist validation
- Replace 8 __import__() with standard imports
- Remove 701 unused imports across 442 files
- Add authorized-testing disclaimers to all offensive skills
- Complete 11 incomplete skill directories
- Expand 10 stub SKILL.md files with full content
- Fix 2 YAML parse errors in frontmatter
- Fix 5 pre-existing syntax errors
- Convert 22 hardcoded paths/ports to environment variables
- Back up 21 redundant skill pairs to .bak
- Fix 2 global declaration errors
- 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE)
- 0 compile errors across all 724 agent.py files
2026-03-19 13:26:49 +01:00

167 lines
6.7 KiB
Python

#!/usr/bin/env python3
"""Agent for performing initial access simulation with Evilginx3 phishlet analysis — educational/authorized pentest use."""
import json
import argparse
import subprocess
import re
from pathlib import Path
def parse_phishlet(phishlet_path):
"""Parse an Evilginx3 YAML phishlet file and extract configuration."""
try:
import yaml
except ImportError:
return {"error": "pyyaml not installed — pip install pyyaml"}
content = Path(phishlet_path).read_text(encoding="utf-8")
config = yaml.safe_load(content)
proxy_hosts = config.get("proxy_hosts", [])
sub_filters = config.get("sub_filters", [])
auth_tokens = config.get("auth_tokens", [])
cred_fields = config.get("credentials", {})
return {
"phishlet": phishlet_path,
"name": config.get("name", ""),
"author": config.get("author", ""),
"target_domain": proxy_hosts[0].get("domain", "") if proxy_hosts else "",
"proxy_hosts": [{"phish_sub": h.get("phish_sub"), "orig_sub": h.get("orig_sub"), "domain": h.get("domain")} for h in proxy_hosts],
"auth_tokens": [{"domain": t.get("domain"), "keys": t.get("keys", [])} for t in auth_tokens],
"credential_fields": cred_fields,
"sub_filters_count": len(sub_filters),
"analysis": {
"captures_session_tokens": len(auth_tokens) > 0,
"captures_credentials": bool(cred_fields),
"mfa_bypass_capable": len(auth_tokens) > 0,
},
}
def analyze_session_log(log_file):
"""Analyze Evilginx session capture logs."""
content = Path(log_file).read_text(encoding="utf-8", errors="replace")
sessions = []
current = {}
for line in content.splitlines():
if "new session" in line.lower() or "session started" in line.lower():
if current:
sessions.append(current)
current = {"start": line.strip(), "tokens": [], "credentials": []}
elif "token" in line.lower() or "cookie" in line.lower():
current.setdefault("tokens", []).append(line.strip()[:200])
elif "username" in line.lower() or "password" in line.lower() or "credential" in line.lower():
current.setdefault("credentials", []).append(line.strip()[:200])
elif "landing_url" in line.lower() or "remote_addr" in line.lower():
ip_match = re.search(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", line)
if ip_match:
current["source_ip"] = ip_match.group()
if current:
sessions.append(current)
return {
"log_file": log_file,
"total_sessions": len(sessions),
"sessions_with_tokens": sum(1 for s in sessions if s.get("tokens")),
"sessions_with_creds": sum(1 for s in sessions if s.get("credentials")),
"sessions": sessions[:20],
}
def check_evilginx_installation():
"""Check if Evilginx3 is installed and get version."""
try:
result = subprocess.run(["evilginx", "--version"], capture_output=True, text=True, timeout=10)
version = result.stdout.strip() or result.stderr.strip()
return {"installed": True, "version": version}
except FileNotFoundError:
return {"installed": False, "error": "evilginx not found in PATH"}
except Exception as e:
return {"installed": False, "error": str(e)}
def list_phishlets(phishlet_dir):
"""List available phishlets in a directory."""
p = Path(phishlet_dir)
if not p.is_dir():
return {"error": f"Directory not found: {phishlet_dir}"}
phishlets = []
for f in sorted(p.glob("*.yaml")) + sorted(p.glob("*.yml")):
phishlets.append({"name": f.stem, "path": str(f), "size": f.stat().st_size})
return {"directory": phishlet_dir, "count": len(phishlets), "phishlets": phishlets}
def generate_detection_rules(phishlet_path):
"""Generate detection signatures for a phishlet's attack patterns."""
try:
import yaml
except ImportError:
return {"error": "pyyaml not installed"}
config = yaml.safe_load(Path(phishlet_path).read_text())
proxy_hosts = config.get("proxy_hosts", [])
rules = []
for host in proxy_hosts:
domain = host.get("domain", "")
phish_sub = host.get("phish_sub", "")
rules.append({
"type": "dns_monitor",
"description": f"Monitor for DNS queries to subdomains impersonating {domain}",
"pattern": f"*.{domain}",
"indicator": f"Phishing subdomain: {phish_sub}.{domain}",
})
auth_tokens = config.get("auth_tokens", [])
for token in auth_tokens:
for key in token.get("keys", []):
rules.append({
"type": "cookie_monitor",
"description": f"Monitor for session token relay of {key}",
"cookie_name": key,
"domain": token.get("domain", ""),
})
rules.append({
"type": "network_signature",
"description": "Detect reverse proxy header anomalies",
"indicators": ["X-Forwarded-For mismatch", "Origin header discrepancy", "TLS certificate mismatch"],
})
return {
"phishlet": phishlet_path,
"detection_rules": rules,
"total_rules": len(rules),
"recommendations": [
"Enable FIDO2/WebAuthn MFA to prevent session token theft",
"Monitor for certificate transparency log entries with suspicious subdomains",
"Deploy conditional access policies requiring compliant devices",
],
}
def main():
parser = argparse.ArgumentParser(description="Evilginx3 Phishlet Analysis Agent (Authorized Testing Only)")
sub = parser.add_subparsers(dest="command")
p = sub.add_parser("parse", help="Parse phishlet YAML")
p.add_argument("--phishlet", required=True)
l = sub.add_parser("logs", help="Analyze session logs")
l.add_argument("--file", required=True)
sub.add_parser("check", help="Check Evilginx installation")
ls = sub.add_parser("list", help="List available phishlets")
ls.add_argument("--dir", required=True)
d = sub.add_parser("detect", help="Generate detection rules")
d.add_argument("--phishlet", required=True)
args = parser.parse_args()
if args.command == "parse":
result = parse_phishlet(args.phishlet)
elif args.command == "logs":
result = analyze_session_log(args.file)
elif args.command == "check":
result = check_evilginx_installation()
elif args.command == "list":
result = list_phishlets(args.dir)
elif args.command == "detect":
result = generate_detection_rules(args.phishlet)
else:
parser.print_help()
return
print(json.dumps(result, indent=2, default=str))
if __name__ == "__main__":
main()