mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-11 18:13:43 +03:00
27c6414ca5
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
235 lines
8.8 KiB
Python
235 lines
8.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Insider Threat Investigation Agent
|
|
Automates insider threat indicator collection by correlating SIEM data,
|
|
DLP alerts, access logs, and HR events to build investigation timelines.
|
|
"""
|
|
|
|
import csv
|
|
import hashlib
|
|
import json
|
|
import os
|
|
import sys
|
|
from datetime import datetime, timezone, timedelta
|
|
|
|
|
|
def load_dlp_alerts(filepath: str) -> list[dict]:
|
|
"""Load DLP alert data from exported CSV."""
|
|
alerts = []
|
|
if not os.path.exists(filepath):
|
|
print(f"[!] DLP alerts file not found: {filepath}")
|
|
return alerts
|
|
with open(filepath, "r", newline="") as f:
|
|
reader = csv.DictReader(f)
|
|
for row in reader:
|
|
alerts.append({
|
|
"timestamp": row.get("timestamp", ""),
|
|
"user": row.get("user", ""),
|
|
"policy": row.get("policy_name", ""),
|
|
"action": row.get("action", ""),
|
|
"destination": row.get("destination", ""),
|
|
"file_count": int(row.get("file_count", 0)),
|
|
"bytes_transferred": int(row.get("bytes_transferred", 0)),
|
|
"severity": row.get("severity", "medium"),
|
|
})
|
|
return alerts
|
|
|
|
|
|
def load_access_logs(filepath: str) -> list[dict]:
|
|
"""Load authentication and access logs from exported JSON."""
|
|
if not os.path.exists(filepath):
|
|
print(f"[!] Access logs file not found: {filepath}")
|
|
return []
|
|
with open(filepath, "r") as f:
|
|
return json.load(f)
|
|
|
|
|
|
def analyze_data_movement(dlp_alerts: list[dict], subject_user: str) -> dict:
|
|
"""Analyze data exfiltration indicators for the subject."""
|
|
user_alerts = [a for a in dlp_alerts if a["user"].lower() == subject_user.lower()]
|
|
|
|
total_bytes = sum(a["bytes_transferred"] for a in user_alerts)
|
|
total_files = sum(a["file_count"] for a in user_alerts)
|
|
destinations = {}
|
|
for alert in user_alerts:
|
|
dest = alert["destination"]
|
|
destinations[dest] = destinations.get(dest, 0) + alert["file_count"]
|
|
|
|
high_severity = [a for a in user_alerts if a["severity"] == "high"]
|
|
|
|
return {
|
|
"total_alerts": len(user_alerts),
|
|
"total_bytes_transferred": total_bytes,
|
|
"total_bytes_gb": round(total_bytes / (1024**3), 2),
|
|
"total_files": total_files,
|
|
"destinations": destinations,
|
|
"high_severity_alerts": len(high_severity),
|
|
"alert_details": user_alerts,
|
|
}
|
|
|
|
|
|
def analyze_access_patterns(access_logs: list[dict], subject_user: str) -> dict:
|
|
"""Detect anomalous access patterns for the subject."""
|
|
user_logs = [l for l in access_logs if l.get("user", "").lower() == subject_user.lower()]
|
|
|
|
off_hours_events = []
|
|
weekend_events = []
|
|
unique_apps = set()
|
|
unique_ips = set()
|
|
|
|
for log in user_logs:
|
|
ts = log.get("timestamp", "")
|
|
try:
|
|
dt = datetime.fromisoformat(ts.replace("Z", "+00:00"))
|
|
hour = dt.hour
|
|
weekday = dt.weekday()
|
|
if hour < 7 or hour > 19:
|
|
off_hours_events.append(log)
|
|
if weekday >= 5:
|
|
weekend_events.append(log)
|
|
except (ValueError, AttributeError):
|
|
pass
|
|
|
|
unique_apps.add(log.get("application", "unknown"))
|
|
unique_ips.add(log.get("source_ip", "unknown"))
|
|
|
|
return {
|
|
"total_events": len(user_logs),
|
|
"off_hours_events": len(off_hours_events),
|
|
"off_hours_pct": round(len(off_hours_events) / max(len(user_logs), 1) * 100, 1),
|
|
"weekend_events": len(weekend_events),
|
|
"weekend_pct": round(len(weekend_events) / max(len(user_logs), 1) * 100, 1),
|
|
"unique_applications": sorted(unique_apps),
|
|
"unique_source_ips": sorted(unique_ips),
|
|
}
|
|
|
|
|
|
def detect_pre_departure_indicators(
|
|
data_movement: dict, access_patterns: dict, notice_date: str
|
|
) -> list[dict]:
|
|
"""Identify pre-departure behavioral indicators."""
|
|
indicators = []
|
|
|
|
if data_movement["total_bytes_gb"] > 1.0:
|
|
indicators.append({
|
|
"severity": "HIGH",
|
|
"indicator": "Bulk data transfer",
|
|
"detail": f"{data_movement['total_bytes_gb']} GB transferred across {data_movement['total_files']} files",
|
|
})
|
|
|
|
if data_movement["high_severity_alerts"] > 0:
|
|
indicators.append({
|
|
"severity": "HIGH",
|
|
"indicator": "High-severity DLP violations",
|
|
"detail": f"{data_movement['high_severity_alerts']} high-severity DLP alerts triggered",
|
|
})
|
|
|
|
personal_storage = ["dropbox", "drive.google", "onedrive.live", "mega.nz", "wetransfer"]
|
|
for dest, count in data_movement["destinations"].items():
|
|
if any(ps in dest.lower() for ps in personal_storage):
|
|
indicators.append({
|
|
"severity": "HIGH",
|
|
"indicator": "Transfer to personal cloud storage",
|
|
"detail": f"{count} files sent to {dest}",
|
|
})
|
|
|
|
if access_patterns["off_hours_pct"] > 30:
|
|
indicators.append({
|
|
"severity": "MEDIUM",
|
|
"indicator": "Elevated off-hours activity",
|
|
"detail": f"{access_patterns['off_hours_pct']}% of activity outside business hours",
|
|
})
|
|
|
|
if access_patterns["weekend_pct"] > 15:
|
|
indicators.append({
|
|
"severity": "MEDIUM",
|
|
"indicator": "Elevated weekend activity",
|
|
"detail": f"{access_patterns['weekend_pct']}% of activity on weekends",
|
|
})
|
|
|
|
if len(access_patterns["unique_applications"]) > 15:
|
|
indicators.append({
|
|
"severity": "MEDIUM",
|
|
"indicator": "Broad application access",
|
|
"detail": f"Accessed {len(access_patterns['unique_applications'])} unique applications",
|
|
})
|
|
|
|
return indicators
|
|
|
|
|
|
def create_evidence_log(case_id: str, evidence_files: list[str]) -> dict:
|
|
"""Create chain-of-custody evidence log with file hashes."""
|
|
items = []
|
|
for filepath in evidence_files:
|
|
if os.path.exists(filepath):
|
|
with open(filepath, "rb") as f:
|
|
content = f.read()
|
|
items.append({
|
|
"item_id": f"EV-{len(items)+1:03d}",
|
|
"file": filepath,
|
|
"sha256": hashlib.sha256(content).hexdigest(),
|
|
"size_bytes": len(content),
|
|
"collected_at": datetime.now(timezone.utc).isoformat(),
|
|
})
|
|
|
|
return {
|
|
"case_id": case_id,
|
|
"created_at": datetime.now(timezone.utc).isoformat(),
|
|
"investigator": os.getenv("USER", "soc_analyst"),
|
|
"evidence_items": items,
|
|
}
|
|
|
|
|
|
def generate_report(case_id: str, subject: str, data_mv: dict, access: dict, indicators: list) -> str:
|
|
"""Generate insider threat investigation report."""
|
|
lines = [
|
|
f"INSIDER THREAT INVESTIGATION REPORT - {case_id}",
|
|
"=" * 55,
|
|
f"Subject: {subject}",
|
|
f"Report Generated: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')}",
|
|
"",
|
|
"DATA MOVEMENT ANALYSIS:",
|
|
f" DLP Alerts: {data_mv['total_alerts']}",
|
|
f" Data Transferred: {data_mv['total_bytes_gb']} GB ({data_mv['total_files']} files)",
|
|
f" High-Severity Alerts: {data_mv['high_severity_alerts']}",
|
|
f" Destinations: {json.dumps(data_mv['destinations'], indent=4)}",
|
|
"",
|
|
"ACCESS PATTERN ANALYSIS:",
|
|
f" Total Events: {access['total_events']}",
|
|
f" Off-Hours Activity: {access['off_hours_pct']}%",
|
|
f" Weekend Activity: {access['weekend_pct']}%",
|
|
f" Applications Accessed: {len(access['unique_applications'])}",
|
|
"",
|
|
f"INDICATORS IDENTIFIED: {len(indicators)}",
|
|
"-" * 40,
|
|
]
|
|
for ind in indicators:
|
|
lines.append(f" [{ind['severity']}] {ind['indicator']}: {ind['detail']}")
|
|
|
|
return "\n".join(lines)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
case_id = sys.argv[1] if len(sys.argv) > 1 else "IT-2024-0001"
|
|
subject_user = sys.argv[2] if len(sys.argv) > 2 else "jsmith"
|
|
dlp_file = sys.argv[3] if len(sys.argv) > 3 else "dlp_alerts.csv"
|
|
access_file = sys.argv[4] if len(sys.argv) > 4 else "access_logs.json"
|
|
|
|
print(f"[*] Starting insider threat investigation: {case_id}")
|
|
print(f"[*] Subject: {subject_user}")
|
|
|
|
dlp_alerts = load_dlp_alerts(dlp_file)
|
|
access_logs = load_access_logs(access_file)
|
|
|
|
data_movement = analyze_data_movement(dlp_alerts, subject_user)
|
|
access_patterns = analyze_access_patterns(access_logs, subject_user)
|
|
indicators = detect_pre_departure_indicators(data_movement, access_patterns, "2024-03-15")
|
|
|
|
report = generate_report(case_id, subject_user, data_movement, access_patterns, indicators)
|
|
print(report)
|
|
|
|
output = f"insider_threat_{case_id}_{datetime.now(timezone.utc).strftime('%Y%m%d')}.json"
|
|
with open(output, "w") as f:
|
|
json.dump({"data_movement": data_movement, "access_patterns": access_patterns, "indicators": indicators}, f, indent=2)
|
|
print(f"\n[*] Results saved to {output}")
|