Files
Anthropic-Cybersecurity-Skills/skills/performing-credential-access-with-lazagne/scripts/process.py
T

198 lines
6.6 KiB
Python

#!/usr/bin/env python3
"""
LaZagne Output Parser and Credential Analysis Script
Parses LaZagne JSON output, deduplicates credentials, and generates
prioritized reports. For authorized red team engagements only.
"""
import json
import sys
import os
from datetime import datetime
from collections import defaultdict
def load_lazagne_output(filepath: str) -> list:
"""Load LaZagne JSON output file."""
try:
with open(filepath, "r") as f:
return json.load(f)
except (FileNotFoundError, json.JSONDecodeError) as e:
print(f"Error loading LaZagne output: {e}")
return []
def parse_credentials(data: list) -> list:
"""Parse LaZagne output into normalized credential entries."""
credentials = []
for module_result in data:
if isinstance(module_result, dict):
category = module_result.get("Category", "Unknown")
results = module_result.get("results", [])
if isinstance(results, list):
for entry in results:
if isinstance(entry, dict):
cred = {
"category": category,
"username": entry.get("Login", entry.get("Username", "")),
"password": entry.get("Password", ""),
"url": entry.get("URL", entry.get("Host", "")),
"port": entry.get("Port", ""),
"source": entry.get("Software", entry.get("Module", category)),
"raw": entry
}
if cred["username"] or cred["password"]:
credentials.append(cred)
return credentials
def deduplicate_credentials(credentials: list) -> list:
"""Remove duplicate credential entries."""
seen = set()
unique = []
for cred in credentials:
key = (
cred["username"].lower(),
cred["password"],
cred["url"].lower() if cred["url"] else ""
)
if key not in seen:
seen.add(key)
unique.append(cred)
return unique
def categorize_credentials(credentials: list) -> dict:
"""Categorize credentials by type and priority."""
categories = {
"domain": [],
"cloud": [],
"database": [],
"remote_access": [],
"email": [],
"web": [],
"other": []
}
cloud_indicators = ["aws", "azure", "gcp", "cloud", "console."]
remote_indicators = ["rdp", "ssh", "vnc", "vpn", "putty", "winscp"]
db_indicators = ["postgres", "mysql", "mssql", "oracle", "mongodb", "redis"]
email_indicators = ["outlook", "thunderbird", "smtp", "imap", "pop3", "mail"]
for cred in credentials:
source_lower = cred["source"].lower()
url_lower = cred["url"].lower() if cred["url"] else ""
combined = source_lower + " " + url_lower
if "\\" in cred["username"] or "@" in cred["username"]:
if any(domain_hint in cred["username"].lower()
for domain_hint in [".local", ".corp", ".internal", "\\"]):
categories["domain"].append(cred)
continue
if any(ind in combined for ind in cloud_indicators):
categories["cloud"].append(cred)
elif any(ind in combined for ind in db_indicators):
categories["database"].append(cred)
elif any(ind in combined for ind in remote_indicators):
categories["remote_access"].append(cred)
elif any(ind in combined for ind in email_indicators):
categories["email"].append(cred)
elif cred["url"]:
categories["web"].append(cred)
else:
categories["other"].append(cred)
return categories
def generate_report(credentials: list, categories: dict, source_file: str) -> str:
"""Generate a credential analysis report."""
report = [
"=" * 70,
"LaZagne Credential Analysis Report",
f"Generated: {datetime.now().isoformat()}",
f"Source File: {source_file}",
"=" * 70,
"",
f"Total Credentials Recovered: {len(credentials)}",
"",
"Breakdown by Priority:",
f" [CRITICAL] Domain Credentials: {len(categories['domain'])}",
f" [HIGH] Cloud Credentials: {len(categories['cloud'])}",
f" [HIGH] Remote Access: {len(categories['remote_access'])}",
f" [MEDIUM] Database Credentials: {len(categories['database'])}",
f" [MEDIUM] Email Credentials: {len(categories['email'])}",
f" [LOW] Web Credentials: {len(categories['web'])}",
f" [INFO] Other: {len(categories['other'])}",
""
]
priority_order = [
("CRITICAL", "Domain Credentials", categories["domain"]),
("HIGH", "Cloud Credentials", categories["cloud"]),
("HIGH", "Remote Access Credentials", categories["remote_access"]),
("MEDIUM", "Database Credentials", categories["database"]),
("MEDIUM", "Email Credentials", categories["email"]),
]
for priority, label, creds in priority_order:
if creds:
report.append(f"[{priority}] {label}:")
report.append("-" * 50)
for cred in creds:
report.append(f" Source: {cred['source']}")
report.append(f" User: {cred['username']}")
report.append(f" Target: {cred['url'] or 'N/A'}")
report.append("")
# Source distribution
source_counts = defaultdict(int)
for cred in credentials:
source_counts[cred["source"]] += 1
report.append("Credentials by Source:")
report.append("-" * 50)
for source, count in sorted(source_counts.items(), key=lambda x: -x[1]):
report.append(f" {source}: {count}")
report.append("")
report.append("=" * 70)
return "\n".join(report)
def main():
"""Main entry point."""
if len(sys.argv) < 2:
print("Usage: python process.py <lazagne_output.json>")
return
input_file = sys.argv[1]
data = load_lazagne_output(input_file)
if not data:
print("No data loaded from LaZagne output.")
return
credentials = parse_credentials(data)
credentials = deduplicate_credentials(credentials)
categories = categorize_credentials(credentials)
report = generate_report(credentials, categories, input_file)
print(report)
report_file = f"credential_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"
with open(report_file, "w") as f:
f.write(report)
print(f"\nReport saved to: {report_file}")
if __name__ == "__main__":
main()