mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-30 07:56:52 +03:00
Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
Complete skill folder anatomy across all cybersecurity skills: - scripts/agent.py: 80-150 line Python agents using real libraries (impacket, boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.) - references/api-reference.md: real API documentation with method signatures - LICENSE: MIT license for all skill folders
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for detecting spearphishing emails using email gateway log analysis."""
|
||||
|
||||
import argparse
|
||||
import email
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from datetime import datetime, timezone
|
||||
from email import policy
|
||||
|
||||
|
||||
EXECUTIVE_TITLES = [
|
||||
"ceo", "cfo", "cto", "cio", "coo", "president", "director",
|
||||
"vp", "vice president", "managing director", "partner",
|
||||
]
|
||||
URGENCY_KEYWORDS = [
|
||||
"urgent", "immediate", "asap", "right away", "time sensitive",
|
||||
"confidential", "do not share", "wire transfer", "bank account",
|
||||
"update payment", "invoice attached", "past due",
|
||||
]
|
||||
SUSPICIOUS_EXTENSIONS = {
|
||||
".exe", ".scr", ".bat", ".cmd", ".ps1", ".vbs", ".js",
|
||||
".hta", ".lnk", ".iso", ".img", ".dll", ".msi",
|
||||
}
|
||||
|
||||
|
||||
def parse_email_headers(eml_path):
|
||||
"""Extract security-relevant headers from an email."""
|
||||
with open(eml_path, "rb") as f:
|
||||
msg = email.message_from_binary_file(f, policy=policy.default)
|
||||
headers = {
|
||||
"from": msg.get("From", ""),
|
||||
"to": msg.get("To", ""),
|
||||
"subject": msg.get("Subject", ""),
|
||||
"reply_to": msg.get("Reply-To", ""),
|
||||
"return_path": msg.get("Return-Path", ""),
|
||||
"received_spf": msg.get("Received-SPF", ""),
|
||||
"dkim_signature": msg.get("DKIM-Signature", ""),
|
||||
"authentication_results": msg.get("Authentication-Results", ""),
|
||||
"x_mailer": msg.get("X-Mailer", ""),
|
||||
"message_id": msg.get("Message-ID", ""),
|
||||
}
|
||||
return headers, msg
|
||||
|
||||
|
||||
def check_authentication(headers):
|
||||
"""Verify SPF, DKIM, DMARC authentication results."""
|
||||
issues = []
|
||||
auth_results = headers.get("authentication_results", "").lower()
|
||||
if "spf=fail" in auth_results or "spf=softfail" in auth_results:
|
||||
issues.append("SPF validation failed")
|
||||
if "dkim=fail" in auth_results:
|
||||
issues.append("DKIM validation failed")
|
||||
if "dmarc=fail" in auth_results:
|
||||
issues.append("DMARC validation failed")
|
||||
if not headers.get("dkim_signature"):
|
||||
issues.append("No DKIM signature present")
|
||||
from_domain = re.search(r"@([\w.-]+)", headers.get("from", ""))
|
||||
reply_domain = re.search(r"@([\w.-]+)", headers.get("reply_to", ""))
|
||||
if from_domain and reply_domain and from_domain.group(1) != reply_domain.group(1):
|
||||
issues.append(f"Reply-To domain mismatch: {reply_domain.group(1)} vs {from_domain.group(1)}")
|
||||
return issues
|
||||
|
||||
|
||||
def check_content_indicators(msg):
|
||||
"""Analyze email body for spearphishing content indicators."""
|
||||
indicators = []
|
||||
body = ""
|
||||
for part in msg.walk():
|
||||
if part.get_content_type() in ("text/plain", "text/html"):
|
||||
payload = part.get_payload(decode=True)
|
||||
if payload:
|
||||
body += payload.decode("utf-8", errors="replace")
|
||||
|
||||
body_lower = body.lower()
|
||||
for kw in URGENCY_KEYWORDS:
|
||||
if kw in body_lower:
|
||||
indicators.append(f"Urgency keyword: '{kw}'")
|
||||
|
||||
urls = re.findall(r'https?://[^\s<>"\']+', body)
|
||||
for url in urls[:10]:
|
||||
if re.search(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', url):
|
||||
indicators.append(f"URL with IP address: {url[:80]}")
|
||||
if len(url) > 100:
|
||||
indicators.append(f"Unusually long URL: {url[:80]}...")
|
||||
|
||||
attachments = []
|
||||
for part in msg.walk():
|
||||
fname = part.get_filename()
|
||||
if fname:
|
||||
ext = os.path.splitext(fname)[1].lower()
|
||||
attachments.append(fname)
|
||||
if ext in SUSPICIOUS_EXTENSIONS:
|
||||
indicators.append(f"Suspicious attachment: {fname}")
|
||||
if ".." in fname or ext == ".exe.pdf":
|
||||
indicators.append(f"Double extension: {fname}")
|
||||
|
||||
return indicators, attachments
|
||||
|
||||
|
||||
def analyze_email(eml_path):
|
||||
"""Full spearphishing analysis of a single email."""
|
||||
headers, msg = parse_email_headers(eml_path)
|
||||
auth_issues = check_authentication(headers)
|
||||
content_indicators, attachments = check_content_indicators(msg)
|
||||
|
||||
all_indicators = auth_issues + content_indicators
|
||||
score = len(all_indicators) * 15
|
||||
risk = "CRITICAL" if score >= 75 else "HIGH" if score >= 50 else "MEDIUM" if score >= 25 else "LOW"
|
||||
|
||||
return {
|
||||
"file": eml_path,
|
||||
"from": headers["from"],
|
||||
"to": headers["to"],
|
||||
"subject": headers["subject"],
|
||||
"auth_issues": auth_issues,
|
||||
"content_indicators": content_indicators,
|
||||
"attachments": attachments,
|
||||
"risk_score": min(score, 100),
|
||||
"risk_level": risk,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Detect spearphishing via email gateway analysis"
|
||||
)
|
||||
parser.add_argument("input", help=".eml file or directory")
|
||||
parser.add_argument("--output", "-o", help="Output JSON report")
|
||||
parser.add_argument("--verbose", "-v", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
print("[*] Spearphishing Detection Agent")
|
||||
results = []
|
||||
|
||||
if os.path.isdir(args.input):
|
||||
for root, _, files in os.walk(args.input):
|
||||
for f in files:
|
||||
if f.lower().endswith(".eml"):
|
||||
results.append(analyze_email(os.path.join(root, f)))
|
||||
else:
|
||||
results.append(analyze_email(args.input))
|
||||
|
||||
flagged = [r for r in results if r["risk_level"] in ("HIGH", "CRITICAL")]
|
||||
report = {
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
"emails_scanned": len(results),
|
||||
"spearphishing_detected": len(flagged),
|
||||
"results": results,
|
||||
}
|
||||
|
||||
print(f"[*] Scanned {len(results)} emails, {len(flagged)} flagged")
|
||||
|
||||
if args.output:
|
||||
with open(args.output, "w") as f:
|
||||
json.dump(report, f, indent=2)
|
||||
print(f"[*] Report saved to {args.output}")
|
||||
else:
|
||||
print(json.dumps(report, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user