mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-08-26 19:29:41 +03:00
Complete folder anatomy for all 649 cybersecurity skills + update LICENSE to Mahipal
- 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
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Adversary Infrastructure Tracking Agent - Tracks threat actor infrastructure using passive DNS and certificate transparency."""
|
||||
|
||||
import json
|
||||
import logging
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
from collections import defaultdict
|
||||
|
||||
import requests
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def query_crtsh(domain):
|
||||
"""Query crt.sh certificate transparency for domain certificates."""
|
||||
resp = requests.get(f"https://crt.sh/?q=%.{domain}&output=json", timeout=30)
|
||||
resp.raise_for_status()
|
||||
certs = resp.json()
|
||||
logger.info("crt.sh: %d certificates for %s", len(certs), domain)
|
||||
return certs
|
||||
|
||||
|
||||
def query_urlhaus(ioc, ioc_type="host"):
|
||||
"""Query URLhaus for malicious URL hosting information."""
|
||||
resp = requests.post("https://urlhaus-api.abuse.ch/v1/host/", data={ioc_type: ioc}, timeout=15)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
|
||||
def query_threatfox(ioc):
|
||||
"""Query ThreatFox for IOC intelligence."""
|
||||
resp = requests.post("https://threatfox-api.abuse.ch/api/v1/", json={"query": "search_ioc", "search_term": ioc}, timeout=15)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
|
||||
def pivot_on_certificate(cert_data):
|
||||
"""Pivot on certificate data to find related infrastructure."""
|
||||
related_domains = set()
|
||||
issuers = defaultdict(list)
|
||||
for cert in cert_data:
|
||||
name_value = cert.get("name_value", "")
|
||||
for domain in name_value.split("\n"):
|
||||
domain = domain.strip().lstrip("*.")
|
||||
if domain:
|
||||
related_domains.add(domain)
|
||||
issuer = cert.get("issuer_name", "")
|
||||
issuers[issuer].append(cert.get("serial_number", ""))
|
||||
return {"related_domains": sorted(related_domains), "issuers": {k: len(v) for k, v in issuers.items()}}
|
||||
|
||||
|
||||
def build_infrastructure_map(seed_iocs, ioc_types):
|
||||
"""Build infrastructure map from seed IOCs."""
|
||||
infra_map = {"nodes": [], "edges": [], "iocs": {}}
|
||||
for ioc, itype in zip(seed_iocs, ioc_types):
|
||||
node = {"ioc": ioc, "type": itype, "sources": []}
|
||||
if itype == "domain":
|
||||
try:
|
||||
certs = query_crtsh(ioc)
|
||||
pivot = pivot_on_certificate(certs)
|
||||
node["ct_domains"] = pivot["related_domains"][:20]
|
||||
node["sources"].append("crt.sh")
|
||||
for related in pivot["related_domains"][:5]:
|
||||
infra_map["edges"].append({"from": ioc, "to": related, "relation": "shared_certificate"})
|
||||
except requests.RequestException as e:
|
||||
node["ct_error"] = str(e)
|
||||
try:
|
||||
urlhaus = query_urlhaus(ioc, "host" if itype == "domain" else "host")
|
||||
if urlhaus.get("query_status") == "ok" and urlhaus.get("urls"):
|
||||
node["urlhaus_urls"] = len(urlhaus.get("urls", []))
|
||||
node["sources"].append("urlhaus")
|
||||
except requests.RequestException:
|
||||
pass
|
||||
try:
|
||||
tf = query_threatfox(ioc)
|
||||
if tf.get("query_status") == "ok" and tf.get("data"):
|
||||
node["threatfox_hits"] = len(tf["data"])
|
||||
node["sources"].append("threatfox")
|
||||
except requests.RequestException:
|
||||
pass
|
||||
infra_map["nodes"].append(node)
|
||||
infra_map["iocs"][ioc] = node
|
||||
return infra_map
|
||||
|
||||
|
||||
def generate_report(infra_map, seed_iocs):
|
||||
"""Generate infrastructure tracking report."""
|
||||
report = {
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"seed_iocs": seed_iocs,
|
||||
"nodes_discovered": len(infra_map["nodes"]),
|
||||
"edges_discovered": len(infra_map["edges"]),
|
||||
"infrastructure_map": infra_map,
|
||||
}
|
||||
print(f"INFRA REPORT: {len(infra_map['nodes'])} nodes, {len(infra_map['edges'])} edges")
|
||||
return report
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Adversary Infrastructure Tracking Agent")
|
||||
parser.add_argument("--iocs", nargs="+", required=True, help="Seed IOCs (domains/IPs)")
|
||||
parser.add_argument("--types", nargs="+", required=True, help="IOC types (domain/ip)")
|
||||
parser.add_argument("--output", default="infra_tracking_report.json")
|
||||
args = parser.parse_args()
|
||||
|
||||
infra_map = build_infrastructure_map(args.iocs, args.types)
|
||||
report = generate_report(infra_map, args.iocs)
|
||||
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()
|
||||
Reference in New Issue
Block a user