mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-11 18:13:43 +03:00
c21af3347e
- Add scripts/agent.py and references/api-reference.md to all remaining skills - Update all 648 LICENSE files: copyright now reads 'Mahipal' - Add implementing-security-monitoring-with-datadog (new skill with full anatomy) - All 649 skills now have: SKILL.md, LICENSE, scripts/agent.py, references/api-reference.md
173 lines
6.6 KiB
Python
173 lines
6.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Threat intelligence enrichment pipeline for Splunk.
|
|
|
|
Manages threat intel lookups, KV store collections, and modular inputs
|
|
for enriching Splunk events with IOC context from MISP, OTX, and CSV feeds.
|
|
"""
|
|
|
|
import sys
|
|
import json
|
|
import csv
|
|
import os
|
|
import datetime
|
|
import io
|
|
|
|
try:
|
|
import requests
|
|
HAS_REQUESTS = True
|
|
except ImportError:
|
|
HAS_REQUESTS = False
|
|
|
|
|
|
SPLUNK_TI_COLLECTIONS = {
|
|
"ip_intel": {
|
|
"fields": ["ip", "threat_key", "description", "source", "weight", "time"],
|
|
"lookup_name": "ip_intel_lookup",
|
|
},
|
|
"domain_intel": {
|
|
"fields": ["domain", "threat_key", "description", "source", "weight", "time"],
|
|
"lookup_name": "domain_intel_lookup",
|
|
},
|
|
"file_intel": {
|
|
"fields": ["file_hash", "file_name", "threat_key", "description", "source", "weight", "time"],
|
|
"lookup_name": "file_intel_lookup",
|
|
},
|
|
"email_intel": {
|
|
"fields": ["src_user", "threat_key", "description", "source", "weight", "time"],
|
|
"lookup_name": "email_intel_lookup",
|
|
},
|
|
}
|
|
|
|
|
|
def fetch_otx_pulse_iocs(pulse_id):
|
|
"""Fetch IOCs from AlienVault OTX pulse."""
|
|
if not HAS_REQUESTS:
|
|
return {"error": "requests not installed"}
|
|
url = "https://otx.alienvault.com/api/v1/pulses/{}/indicators".format(pulse_id)
|
|
try:
|
|
resp = requests.get(url, timeout=15)
|
|
if resp.status_code == 200:
|
|
data = resp.json()
|
|
iocs = []
|
|
for ind in data.get("results", []):
|
|
iocs.append({
|
|
"type": ind.get("type", ""),
|
|
"indicator": ind.get("indicator", ""),
|
|
"title": ind.get("title", ""),
|
|
"created": ind.get("created", ""),
|
|
})
|
|
return {"pulse_id": pulse_id, "count": len(iocs), "indicators": iocs}
|
|
return {"error": "HTTP {}".format(resp.status_code)}
|
|
except Exception as e:
|
|
return {"error": str(e)}
|
|
|
|
|
|
def convert_iocs_to_splunk_lookup(iocs, collection_type="ip_intel"):
|
|
"""Convert IOC list to Splunk KV store format."""
|
|
collection = SPLUNK_TI_COLLECTIONS.get(collection_type, SPLUNK_TI_COLLECTIONS["ip_intel"])
|
|
rows = []
|
|
now = datetime.datetime.utcnow().isoformat() + "Z"
|
|
for ioc in iocs:
|
|
if collection_type == "ip_intel" and ioc.get("type") in ("IPv4", "IPv6"):
|
|
rows.append({
|
|
"ip": ioc["indicator"],
|
|
"threat_key": ioc.get("title", "malicious_ip"),
|
|
"description": "OTX: " + ioc.get("title", ""),
|
|
"source": "otx",
|
|
"weight": "3",
|
|
"time": now,
|
|
})
|
|
elif collection_type == "domain_intel" and ioc.get("type") in ("domain", "hostname"):
|
|
rows.append({
|
|
"domain": ioc["indicator"],
|
|
"threat_key": ioc.get("title", "malicious_domain"),
|
|
"description": "OTX: " + ioc.get("title", ""),
|
|
"source": "otx",
|
|
"weight": "3",
|
|
"time": now,
|
|
})
|
|
elif collection_type == "file_intel" and ioc.get("type") in ("FileHash-SHA256", "FileHash-MD5"):
|
|
rows.append({
|
|
"file_hash": ioc["indicator"],
|
|
"file_name": "",
|
|
"threat_key": ioc.get("title", "malicious_file"),
|
|
"description": "OTX: " + ioc.get("title", ""),
|
|
"source": "otx",
|
|
"weight": "3",
|
|
"time": now,
|
|
})
|
|
return {"collection": collection_type, "lookup_name": collection["lookup_name"], "row_count": len(rows), "rows": rows}
|
|
|
|
|
|
def generate_splunk_lookup_csv(rows, output_path=None):
|
|
"""Generate CSV file for Splunk lookup table."""
|
|
if not rows:
|
|
return ""
|
|
output = io.StringIO()
|
|
writer = csv.DictWriter(output, fieldnames=rows[0].keys())
|
|
writer.writeheader()
|
|
writer.writerows(rows)
|
|
csv_content = output.getvalue()
|
|
if output_path:
|
|
with open(output_path, "w", encoding="utf-8") as f:
|
|
f.write(csv_content)
|
|
return csv_content
|
|
|
|
|
|
def build_spl_correlation_search(collection_type="ip_intel"):
|
|
"""Build SPL query for threat intelligence correlation."""
|
|
queries = {
|
|
"ip_intel": (
|
|
'| tstats summariesonly=t count from datamodel=Network_Traffic '
|
|
'by All_Traffic.dest_ip '
|
|
'| rename All_Traffic.dest_ip as ip '
|
|
'| lookup ip_intel_lookup ip OUTPUT threat_key description source '
|
|
'| where isnotnull(threat_key) '
|
|
'| table ip threat_key description source count'
|
|
),
|
|
"domain_intel": (
|
|
'| tstats summariesonly=t count from datamodel=Network_Resolution '
|
|
'by DNS.query '
|
|
'| rename DNS.query as domain '
|
|
'| lookup domain_intel_lookup domain OUTPUT threat_key description source '
|
|
'| where isnotnull(threat_key) '
|
|
'| table domain threat_key description source count'
|
|
),
|
|
"file_intel": (
|
|
'index=endpoint sourcetype=sysmon EventCode=1 '
|
|
'| lookup file_intel_lookup file_hash as Hashes OUTPUT threat_key description '
|
|
'| where isnotnull(threat_key) '
|
|
'| table _time Computer Image Hashes threat_key description'
|
|
),
|
|
}
|
|
return queries.get(collection_type, "| makeresults | eval error=\"Unknown collection\"")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("=" * 60)
|
|
print("Threat Intelligence Enrichment in Splunk")
|
|
print("KV store collections, lookup tables, SPL correlation")
|
|
print("=" * 60)
|
|
print(" requests available: {}".format(HAS_REQUESTS))
|
|
|
|
print("\n--- Splunk TI Collections ---")
|
|
for name, info in SPLUNK_TI_COLLECTIONS.items():
|
|
print(" {}: lookup={}, fields={}".format(name, info["lookup_name"], len(info["fields"])))
|
|
|
|
print("\n--- SPL Correlation Queries ---")
|
|
for ctype in ["ip_intel", "domain_intel", "file_intel"]:
|
|
spl = build_spl_correlation_search(ctype)
|
|
print(" [{}] {}...".format(ctype, spl[:80]))
|
|
|
|
demo_iocs = [
|
|
{"type": "IPv4", "indicator": "198.51.100.42", "title": "C2 Server"},
|
|
{"type": "domain", "indicator": "evil.example.com", "title": "Phishing Domain"},
|
|
{"type": "FileHash-SHA256", "indicator": "a" * 64, "title": "Malware Sample"},
|
|
]
|
|
for ctype in ["ip_intel", "domain_intel", "file_intel"]:
|
|
result = convert_iocs_to_splunk_lookup(demo_iocs, ctype)
|
|
if result["row_count"] > 0:
|
|
print("\n Converted {} IOCs to {} format".format(result["row_count"], ctype))
|
|
|
|
print("\n" + json.dumps({"collections_configured": len(SPLUNK_TI_COLLECTIONS)}, indent=2))
|