Files
Anthropic-Cybersecurity-Skills/skills/analyzing-threat-landscape-with-misp/scripts/agent.py
T
mukul975 27c6414ca5 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
2026-03-10 21:02:12 +01:00

178 lines
6.6 KiB
Python

#!/usr/bin/env python3
"""MISP Threat Landscape Analysis Agent - Generates threat landscape reports from MISP event data."""
import json
import logging
import argparse
from datetime import datetime, timedelta
from collections import defaultdict, Counter
from pymisp import PyMISP
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
THREAT_LEVELS = {1: "High", 2: "Medium", 3: "Low", 4: "Undefined"}
ANALYSIS_LEVELS = {0: "Initial", 1: "Ongoing", 2: "Completed"}
MITRE_TAG_PREFIX = "misp-galaxy:mitre-attack-pattern="
THREAT_ACTOR_PREFIX = "misp-galaxy:threat-actor="
MALWARE_PREFIX = "misp-galaxy:malpedia="
def connect_misp(url, api_key, ssl=True):
"""Connect to MISP instance."""
misp = PyMISP(url, api_key, ssl=ssl)
logger.info("Connected to MISP: %s", url)
return misp
def fetch_events(misp, days=90):
"""Fetch events from the last N days."""
date_from = (datetime.utcnow() - timedelta(days=days)).strftime("%Y-%m-%d")
events = misp.search(date_from=date_from, pythonify=True)
logger.info("Fetched %d events from last %d days", len(events), days)
return events
def analyze_threat_levels(events):
"""Break down events by threat level."""
counter = Counter()
for event in events:
level = getattr(event, "threat_level_id", 4)
counter[THREAT_LEVELS.get(int(level), "Undefined")] += 1
total = sum(counter.values()) or 1
return {level: {"count": count, "percent": round(count / total * 100, 1)} for level, count in counter.most_common()}
def analyze_attribute_types(events):
"""Analyze distribution of attribute types across events."""
counter = Counter()
for event in events:
for attr in getattr(event, "Attribute", []):
counter[attr.type] += 1
total = sum(counter.values()) or 1
return {
atype: {"count": count, "percent": round(count / total * 100, 1)}
for atype, count in counter.most_common(20)
}
def extract_tags(events):
"""Extract and categorize tags from events."""
mitre_techniques = Counter()
threat_actors = Counter()
malware_families = Counter()
all_tags = Counter()
for event in events:
for tag in getattr(event, "Tag", []):
tag_name = tag.name
all_tags[tag_name] += 1
if tag_name.startswith(MITRE_TAG_PREFIX):
technique = tag_name[len(MITRE_TAG_PREFIX):].strip('"').strip("'")
mitre_techniques[technique] += 1
elif tag_name.startswith(THREAT_ACTOR_PREFIX):
actor = tag_name[len(THREAT_ACTOR_PREFIX):].strip('"').strip("'")
threat_actors[actor] += 1
elif tag_name.startswith(MALWARE_PREFIX):
malware = tag_name[len(MALWARE_PREFIX):].strip('"').strip("'")
malware_families[malware] += 1
return {
"mitre_techniques": dict(mitre_techniques.most_common(20)),
"threat_actors": dict(threat_actors.most_common(20)),
"malware_families": dict(malware_families.most_common(20)),
"top_tags": dict(all_tags.most_common(30)),
}
def analyze_temporal_trends(events, days=90):
"""Analyze event creation trends over time (weekly buckets)."""
buckets = defaultdict(int)
for event in events:
event_date = getattr(event, "date", None)
if event_date:
if isinstance(event_date, str):
event_date = datetime.strptime(event_date, "%Y-%m-%d")
week_start = event_date - timedelta(days=event_date.weekday())
buckets[week_start.strftime("%Y-%m-%d")] += 1
return dict(sorted(buckets.items()))
def analyze_organizations(events):
"""Analyze contributing organizations."""
org_counter = Counter()
for event in events:
org = getattr(event, "Orgc", None)
if org:
org_name = getattr(org, "name", "Unknown")
org_counter[org_name] += 1
return dict(org_counter.most_common(20))
def compute_ioc_stats(events):
"""Compute IOC statistics: total count, unique values, categories."""
ioc_values = set()
category_counter = Counter()
for event in events:
for attr in getattr(event, "Attribute", []):
ioc_values.add(attr.value)
category_counter[attr.category] += 1
return {
"total_attributes": sum(category_counter.values()),
"unique_values": len(ioc_values),
"categories": dict(category_counter.most_common(15)),
}
def generate_report(events, threat_levels, attr_types, tags, trends, orgs, ioc_stats, days):
"""Generate threat landscape report."""
report = {
"timestamp": datetime.utcnow().isoformat(),
"period_days": days,
"total_events": len(events),
"threat_level_distribution": threat_levels,
"attribute_type_distribution": attr_types,
"ioc_statistics": ioc_stats,
"mitre_attack_techniques": tags["mitre_techniques"],
"top_threat_actors": tags["threat_actors"],
"top_malware_families": tags["malware_families"],
"temporal_trends": trends,
"contributing_organizations": orgs,
}
high_pct = threat_levels.get("High", {}).get("percent", 0)
top_technique = next(iter(tags["mitre_techniques"]), "N/A")
top_actor = next(iter(tags["threat_actors"]), "N/A")
print(f"THREAT LANDSCAPE: {len(events)} events, {high_pct}% high severity, top technique: {top_technique}, top actor: {top_actor}")
return report
def main():
parser = argparse.ArgumentParser(description="MISP Threat Landscape Analysis Agent")
parser.add_argument("--misp-url", required=True, help="MISP instance URL")
parser.add_argument("--api-key", required=True, help="MISP API key")
parser.add_argument("--days", type=int, default=90, help="Analysis period in days")
parser.add_argument("--no-ssl", action="store_true", help="Disable SSL verification")
parser.add_argument("--output", default="landscape_report.json")
args = parser.parse_args()
misp = connect_misp(args.misp_url, args.api_key, ssl=not args.no_ssl)
events = fetch_events(misp, args.days)
threat_levels = analyze_threat_levels(events)
attr_types = analyze_attribute_types(events)
tags = extract_tags(events)
trends = analyze_temporal_trends(events, args.days)
orgs = analyze_organizations(events)
ioc_stats = compute_ioc_stats(events)
report = generate_report(events, threat_levels, attr_types, tags, trends, orgs, ioc_stats, args.days)
with open(args.output, "w") as f:
json.dump(report, f, indent=2)
logger.info("Report saved to %s", args.output)
if __name__ == "__main__":
main()