mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-14 06:54:57 +03:00
197 lines
7.4 KiB
Python
197 lines
7.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Social Engineering Penetration Test — Campaign Metrics Processor
|
|
|
|
Processes GoPhish campaign results and generates analysis reports.
|
|
Requires: requests library for GoPhish API interaction.
|
|
|
|
Usage:
|
|
python process.py --gophish-url https://localhost:3333 --api-key <key> --output ./results
|
|
"""
|
|
|
|
import json
|
|
import csv
|
|
import argparse
|
|
import datetime
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
try:
|
|
import requests
|
|
requests.packages.urllib3.disable_warnings()
|
|
except ImportError:
|
|
print("Install requests: pip install requests")
|
|
raise
|
|
|
|
|
|
class GoPhishClient:
|
|
"""Client for GoPhish REST API."""
|
|
|
|
def __init__(self, base_url: str, api_key: str):
|
|
self.base_url = base_url.rstrip("/")
|
|
self.headers = {"Authorization": f"Bearer {api_key}"}
|
|
self.session = requests.Session()
|
|
self.session.headers.update(self.headers)
|
|
self.session.verify = False
|
|
|
|
def get_campaigns(self) -> list[dict]:
|
|
resp = self.session.get(f"{self.base_url}/api/campaigns/")
|
|
resp.raise_for_status()
|
|
return resp.json()
|
|
|
|
def get_campaign(self, campaign_id: int) -> dict:
|
|
resp = self.session.get(f"{self.base_url}/api/campaigns/{campaign_id}")
|
|
resp.raise_for_status()
|
|
return resp.json()
|
|
|
|
def get_campaign_results(self, campaign_id: int) -> dict:
|
|
resp = self.session.get(f"{self.base_url}/api/campaigns/{campaign_id}/results")
|
|
resp.raise_for_status()
|
|
return resp.json()
|
|
|
|
|
|
def analyze_campaign(campaign: dict) -> dict:
|
|
"""Analyze a single campaign's results."""
|
|
results = campaign.get("results", [])
|
|
timeline = campaign.get("timeline", [])
|
|
|
|
stats = {
|
|
"campaign_name": campaign.get("name", "Unknown"),
|
|
"total_targets": len(results),
|
|
"emails_sent": 0,
|
|
"emails_opened": 0,
|
|
"links_clicked": 0,
|
|
"credentials_submitted": 0,
|
|
"emails_reported": 0,
|
|
"errors": 0,
|
|
}
|
|
|
|
for entry in results:
|
|
status = entry.get("status", "")
|
|
if status == "Email Sent" or status in ("Email Opened", "Clicked Link",
|
|
"Submitted Data", "Email Reported"):
|
|
stats["emails_sent"] += 1
|
|
if status in ("Email Opened", "Clicked Link", "Submitted Data"):
|
|
stats["emails_opened"] += 1
|
|
if status in ("Clicked Link", "Submitted Data"):
|
|
stats["links_clicked"] += 1
|
|
if status == "Submitted Data":
|
|
stats["credentials_submitted"] += 1
|
|
if status == "Email Reported":
|
|
stats["emails_reported"] += 1
|
|
if status == "Error":
|
|
stats["errors"] += 1
|
|
|
|
# Calculate rates
|
|
total = stats["total_targets"]
|
|
if total > 0:
|
|
stats["open_rate"] = round(stats["emails_opened"] / total * 100, 1)
|
|
stats["click_rate"] = round(stats["links_clicked"] / total * 100, 1)
|
|
stats["submit_rate"] = round(stats["credentials_submitted"] / total * 100, 1)
|
|
stats["report_rate"] = round(stats["emails_reported"] / total * 100, 1)
|
|
else:
|
|
stats["open_rate"] = stats["click_rate"] = stats["submit_rate"] = stats["report_rate"] = 0
|
|
|
|
return stats
|
|
|
|
|
|
def analyze_by_department(results: list[dict]) -> dict[str, dict]:
|
|
"""Break down results by department/position."""
|
|
departments = {}
|
|
for entry in results:
|
|
dept = entry.get("position", "Unknown")
|
|
if dept not in departments:
|
|
departments[dept] = {
|
|
"total": 0, "clicked": 0, "submitted": 0, "reported": 0
|
|
}
|
|
departments[dept]["total"] += 1
|
|
status = entry.get("status", "")
|
|
if status in ("Clicked Link", "Submitted Data"):
|
|
departments[dept]["clicked"] += 1
|
|
if status == "Submitted Data":
|
|
departments[dept]["submitted"] += 1
|
|
if status == "Email Reported":
|
|
departments[dept]["reported"] += 1
|
|
|
|
return departments
|
|
|
|
|
|
def generate_report(stats: dict, dept_analysis: dict, output_dir: Path) -> str:
|
|
"""Generate campaign analysis report."""
|
|
report_file = output_dir / "se_campaign_report.md"
|
|
timestamp = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
|
|
|
|
with open(report_file, "w") as f:
|
|
f.write("# Social Engineering Campaign Analysis Report\n\n")
|
|
f.write(f"**Campaign:** {stats['campaign_name']}\n")
|
|
f.write(f"**Generated:** {timestamp}\n\n---\n\n")
|
|
|
|
f.write("## Campaign Metrics\n\n")
|
|
f.write("| Metric | Count | Rate |\n")
|
|
f.write("|--------|-------|------|\n")
|
|
f.write(f"| Targets | {stats['total_targets']} | 100% |\n")
|
|
f.write(f"| Emails Sent | {stats['emails_sent']} | — |\n")
|
|
f.write(f"| Emails Opened | {stats['emails_opened']} | {stats['open_rate']}% |\n")
|
|
f.write(f"| Links Clicked | {stats['links_clicked']} | {stats['click_rate']}% |\n")
|
|
f.write(f"| Credentials Submitted | {stats['credentials_submitted']} | {stats['submit_rate']}% |\n")
|
|
f.write(f"| Reported to Security | {stats['emails_reported']} | {stats['report_rate']}% |\n\n")
|
|
|
|
f.write("## Department Breakdown\n\n")
|
|
f.write("| Department | Total | Clicked | Submitted | Reported |\n")
|
|
f.write("|-----------|-------|---------|-----------|----------|\n")
|
|
for dept, data in sorted(dept_analysis.items()):
|
|
f.write(f"| {dept} | {data['total']} | {data['clicked']} | {data['submitted']} | {data['reported']} |\n")
|
|
f.write("\n")
|
|
|
|
f.write("## Risk Assessment\n\n")
|
|
if stats["submit_rate"] > 20:
|
|
risk = "CRITICAL"
|
|
elif stats["submit_rate"] > 10:
|
|
risk = "HIGH"
|
|
elif stats["submit_rate"] > 5:
|
|
risk = "MEDIUM"
|
|
else:
|
|
risk = "LOW"
|
|
f.write(f"**Overall Risk Level: {risk}**\n\n")
|
|
|
|
f.write("## Recommendations\n\n")
|
|
f.write("1. Deploy phishing-resistant MFA (FIDO2/WebAuthn)\n")
|
|
f.write("2. Implement targeted training for high-risk departments\n")
|
|
f.write("3. Deploy email security gateway with URL sandboxing\n")
|
|
f.write("4. Establish phishing report button and reward program\n")
|
|
f.write("5. Conduct quarterly phishing simulations\n")
|
|
|
|
print(f"[+] Report: {report_file}")
|
|
return str(report_file)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="SE Campaign Analysis")
|
|
parser.add_argument("--gophish-url", default="https://localhost:3333")
|
|
parser.add_argument("--api-key", required=True)
|
|
parser.add_argument("--campaign-id", type=int, help="Specific campaign ID")
|
|
parser.add_argument("--output", default="./results")
|
|
args = parser.parse_args()
|
|
|
|
output_dir = Path(args.output)
|
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
client = GoPhishClient(args.gophish_url, args.api_key)
|
|
|
|
if args.campaign_id:
|
|
campaign = client.get_campaign(args.campaign_id)
|
|
stats = analyze_campaign(campaign)
|
|
dept_analysis = analyze_by_department(campaign.get("results", []))
|
|
generate_report(stats, dept_analysis, output_dir)
|
|
else:
|
|
campaigns = client.get_campaigns()
|
|
for campaign in campaigns:
|
|
stats = analyze_campaign(campaign)
|
|
dept_analysis = analyze_by_department(campaign.get("results", []))
|
|
generate_report(stats, dept_analysis, output_dir)
|
|
print(f"[+] Processed campaign: {campaign.get('name')}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|