[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6AECCYSF2ACX260WQ4J6B96":3,"skill-same:01M6AECCYSF2ACX260WQ4J6B96":105},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":64,"commitSha":65,"skillDirectory":66,"forksCount":67,"repositoryHtmlUrl":68,"repositoryHomepageUrl":69,"ownerHtmlUrl":70,"ownerBlogUrl":71,"ownerDescription":72,"updatedAt":73,"install":74,"resources":87},"01M6AECCYSF2ACX260WQ4J6B96","detecting-dns-exfiltration-with-dns-query-analysis",null,"Detect data exfiltration via DNS tunneling (tools like iodine, dnscat2, dns2tcp) by analyzing query entropy, subdomain length, query volume to single domains, TXT\u002FCNAME\u002FNULL record abuse, and oversized response payloads using passive DNS monitoring and statistical\u002FML methods. Use when hunting for covert DNS-based data exfiltration or building a passive DNS anomaly detection capability.","mukul975\u002FAnthropic-Cybersecurity-Skills","mukul975","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F42860185?v=4","01M6ADEQR8T5M4EEG6C67BQCWF","Mahipal","01M6ADJPMYWG1E5GM1FWBE3128",36078,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fdetecting-dns-exfiltration-with-dns-query-analysis\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"detecting dns exfiltration with dns query analysis","dns","exfiltration","analyzing","dnscat2","iodine","entropy-analysis","dns-exfiltration","network-monitoring","network-security","data","network","security","data-exfiltration","threat-detection","dns-tunneling","monitoring","pr","ml","cybersecurity","2026-11-10 10:12:30",false,"---\nname: detecting-dns-exfiltration-with-dns-query-analysis\ndescription: Detect data exfiltration via DNS tunneling (tools like iodine, dnscat2, dns2tcp) by analyzing query entropy, subdomain length, query volume to single domains, TXT\u002FCNAME\u002FNULL record abuse, and oversized response payloads using passive DNS monitoring and statistical\u002FML methods. Use when hunting for covert DNS-based data exfiltration or building a passive DNS anomaly detection capability.\ndomain: cybersecurity\nsubdomain: network-security\ntags:\n- dns-exfiltration\n- dns-tunneling\n- data-exfiltration\n- threat-detection\n- entropy-analysis\n- passive-dns\n- network-monitoring\n- iodine\n- dnscat2\nversion: '1.0'\nauthor: mahipal\nlicense: Apache-2.0\nnist_csf:\n- PR.IR-01\n- DE.CM-01\n- ID.AM-03\n- PR.DS-02\nmitre_attack:\n- T1046\n- T1040\n- T1557\n- T1071\n- T1048\n---\n\n# Detecting DNS Exfiltration with DNS Query Analysis\n\n## Overview\n\nDNS exfiltration exploits the Domain Name System as a covert channel to extract data from compromised networks. Attackers encode stolen data into DNS query names (subdomains) or DNS response records (TXT, CNAME, NULL), bypassing traditional security controls that typically allow DNS traffic unrestricted. Tools like iodine, dnscat2, and dns2tcp enable full TCP tunneling over DNS. Detection requires analyzing DNS query patterns for anomalies including excessive query length, high entropy subdomain strings, abnormal query volumes to single domains, and oversized TXT record responses. This skill covers building a comprehensive DNS exfiltration detection capability using passive DNS analysis, statistical methods, and machine learning approaches.\n\n\n## When to Use\n\n- When investigating security incidents that require detecting dns exfiltration with dns query analysis\n- When building detection rules or threat hunting queries for this domain\n- When SOC analysts need structured procedures for this analysis type\n- When validating security monitoring coverage for related attack techniques\n\n## Prerequisites\n\n- Access to DNS query logs (passive DNS capture, DNS server logs, or PCAP)\n- Zeek, Suricata, or tcpdump for DNS traffic capture\n- Python 3.8+ with scipy, numpy, pandas, and scikit-learn\n- SIEM platform for alert correlation\n- Baseline of normal DNS traffic patterns for the environment\n\n## Core Concepts\n\n### DNS Tunneling Mechanics\n\nDNS exfiltration encodes data in different parts of DNS messages:\n\n**Outbound (Query-based exfiltration):**\n```\nEncoded data as subdomain labels:\ndGhlIHNlY3JldCBkYXRh.exfil.attacker.com\n[base64-encoded data].[tunnel domain]\n\nQuery types used: A, AAAA, CNAME, MX, TXT, NULL\n```\n\n**Inbound (Response-based command channel):**\n```\nTXT records carry encoded commands\u002Fdata in responses\nCNAME records chain encoded data through multiple labels\nNULL records carry arbitrary binary data\n```\n\n### Detection Indicators\n\n| Indicator | Normal DNS | DNS Tunneling |\n|-----------|-----------|---------------|\n| Subdomain length | 5-20 chars | 40-253 chars |\n| Label count | 2-4 labels | 5-10+ labels |\n| Shannon entropy | 2.5-3.5 bits | 4.0-5.5 bits |\n| Query volume (per domain) | Variable | 100s-1000s\u002Fmin |\n| TXT response size | \u003C 100 bytes | 200-4000+ bytes |\n| Unique subdomains | Low | Very high |\n| Query type distribution | Mostly A\u002FAAAA | Heavy TXT, NULL, CNAME |\n\n### Common Tunneling Tools\n\n| Tool | Protocol | Encoding | Detection Difficulty |\n|------|----------|----------|---------------------|\n| iodine | IP-over-DNS | Base32\u002FBase64\u002FRaw | Medium |\n| dnscat2 | TCP-over-DNS | Hex encoding | Medium |\n| dns2tcp | TCP-over-DNS | Base64 | Medium |\n| DNSExfiltrator | Custom | Base64 | Low |\n| Cobalt Strike DNS | C2 over DNS | Custom encoding | High |\n\n## Workflow\n\n### Step 1: Capture DNS Traffic\n\n**Using Zeek:**\n```bash\n# Live capture\nzeek -i eth0 -C base\u002Fprotocols\u002Fdns\n\n# Offline PCAP analysis\nzeek -r traffic.pcap base\u002Fprotocols\u002Fdns\n\n# Output: dns.log with query, qtype, answers, TTL\n```\n\n**Using tcpdump:**\n```bash\n# Capture all DNS traffic\ntcpdump -i eth0 -w dns_capture.pcap port 53\n\n# Capture with size filter (large DNS packets)\ntcpdump -i eth0 -w large_dns.pcap 'port 53 and greater 512'\n```\n\n**Using Suricata:**\n```yaml\n# In suricata.yaml, enable DNS logging\noutputs:\n  - eve-log:\n      types:\n        - dns:\n            query: yes\n            answer: yes\n            formats: [detailed]\n```\n\n### Step 2: Analyze Query Characteristics\n\nPython script for DNS exfiltration detection:\n\n```python\n#!\u002Fusr\u002Fbin\u002Fenv python3\n\"\"\"DNS Exfiltration Detector - Analyzes DNS logs for tunneling indicators.\"\"\"\n\nimport json\nimport math\nimport re\nimport sys\nfrom collections import defaultdict\nfrom datetime import datetime, timedelta\n\nimport pandas as pd\n\n\ndef calculate_entropy(domain: str) -> float:\n    \"\"\"Calculate Shannon entropy of a string.\"\"\"\n    if not domain:\n        return 0.0\n    freq = defaultdict(int)\n    for char in domain:\n        freq[char] += 1\n    length = len(domain)\n    entropy = -sum(\n        (count \u002F length) * math.log2(count \u002F length)\n        for count in freq.values()\n    )\n    return entropy\n\n\ndef extract_subdomain(query: str) -> str:\n    \"\"\"Extract subdomain portion from FQDN.\"\"\"\n    parts = query.rstrip('.').split('.')\n    if len(parts) > 2:\n        return '.'.join(parts[:-2])\n    return ''\n\n\ndef get_base_domain(query: str) -> str:\n    \"\"\"Extract registered domain from FQDN.\"\"\"\n    parts = query.rstrip('.').split('.')\n    if len(parts) >= 2:\n        return '.'.join(parts[-2:])\n    return query\n\n\ndef is_base64_like(s: str) -> bool:\n    \"\"\"Check if string resembles base64 encoding.\"\"\"\n    b64_chars = set('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+\u002F=')\n    if len(s) \u003C 10:\n        return False\n    char_ratio = sum(1 for c in s if c in b64_chars) \u002F len(s)\n    return char_ratio > 0.9 and calculate_entropy(s) > 4.0\n\n\ndef is_hex_encoded(s: str) -> bool:\n    \"\"\"Check if string appears hex-encoded.\"\"\"\n    hex_chars = set('0123456789abcdefABCDEF')\n    if len(s) \u003C 16:\n        return False\n    clean = s.replace('.', '').replace('-', '')\n    return all(c in hex_chars for c in clean) and len(clean) % 2 == 0\n\n\nclass DNSExfiltrationDetector:\n    def __init__(self):\n        self.domain_stats = defaultdict(lambda: {\n            'query_count': 0,\n            'unique_subdomains': set(),\n            'total_subdomain_length': 0,\n            'entropy_sum': 0.0,\n            'query_types': defaultdict(int),\n            'source_ips': set(),\n            'first_seen': None,\n            'last_seen': None,\n            'txt_response_sizes': [],\n        })\n\n        # Detection thresholds\n        self.thresholds = {\n            'min_query_count': 50,\n            'min_unique_subdomains': 30,\n            'avg_subdomain_length': 30,\n            'avg_entropy': 3.8,\n            'unique_ratio': 0.7,\n            'txt_query_ratio': 0.3,\n            'max_label_length': 63,\n            'max_subdomain_labels': 5,\n        }\n\n    def process_query(self, timestamp, src_ip, query, qtype, response_size=0):\n        \"\"\"Process a single DNS query and update statistics.\"\"\"\n        base_domain = get_base_domain(query)\n        subdomain = extract_subdomain(query)\n\n        stats = self.domain_stats[base_domain]\n        stats['query_count'] += 1\n        stats['unique_subdomains'].add(subdomain)\n        stats['total_subdomain_length'] += len(subdomain)\n        stats['entropy_sum'] += calculate_entropy(subdomain)\n        stats['query_types'][qtype] += 1\n        stats['source_ips'].add(src_ip)\n\n        if stats['first_seen'] is None:\n            stats['first_seen'] = timestamp\n        stats['last_seen'] = timestamp\n\n        if qtype in ('TXT', 'NULL') and response_size > 0:\n            stats['txt_response_sizes'].append(response_size)\n\n    def analyze(self):\n        \"\"\"Analyze accumulated statistics and return suspicious domains.\"\"\"\n        alerts = []\n\n        for domain, stats in self.domain_stats.items():\n            if stats['query_count'] \u003C self.thresholds['min_query_count']:\n                continue\n\n            unique_count = len(stats['unique_subdomains'])\n            avg_length = stats['total_subdomain_length'] \u002F stats['query_count']\n            avg_entropy = stats['entropy_sum'] \u002F stats['query_count']\n            unique_ratio = unique_count \u002F stats['query_count']\n\n            txt_queries = stats['query_types'].get('TXT', 0) + stats['query_types'].get('NULL', 0)\n            txt_ratio = txt_queries \u002F stats['query_count']\n\n            score = 0\n            indicators = []\n\n            if avg_length > self.thresholds['avg_subdomain_length']:\n                score += 25\n                indicators.append(f\"high_avg_subdomain_length={avg_length:.1f}\")\n\n            if avg_entropy > self.thresholds['avg_entropy']:\n                score += 25\n                indicators.append(f\"high_entropy={avg_entropy:.2f}\")\n\n            if unique_ratio > self.thresholds['unique_ratio']:\n                score += 20\n                indicators.append(f\"high_unique_ratio={unique_ratio:.2f}\")\n\n            if txt_ratio > self.thresholds['txt_query_ratio']:\n                score += 15\n                indicators.append(f\"high_txt_ratio={txt_ratio:.2f}\")\n\n            if unique_count > self.thresholds['min_unique_subdomains']:\n                score += 15\n                indicators.append(f\"unique_subdomains={unique_count}\")\n\n            # Check for encoding patterns\n            encoded_count = sum(\n                1 for sd in list(stats['unique_subdomains'])[:100]\n                if is_base64_like(sd) or is_hex_encoded(sd)\n            )\n            if encoded_count > 20:\n                score += 20\n                indicators.append(f\"encoded_subdomains={encoded_count}\")\n\n            if score >= 50:\n                duration = (stats['last_seen'] - stats['first_seen']).total_seconds() if stats['first_seen'] and stats['last_seen'] else 0\n                alerts.append({\n                    'domain': domain,\n                    'score': min(score, 100),\n                    'query_count': stats['query_count'],\n                    'unique_subdomains': unique_count,\n                    'avg_subdomain_length': round(avg_length, 1),\n                    'avg_entropy': round(avg_entropy, 2),\n                    'unique_ratio': round(unique_ratio, 2),\n                    'txt_ratio': round(txt_ratio, 2),\n                    'source_ips': list(stats['source_ips']),\n                    'duration_seconds': duration,\n                    'indicators': indicators,\n                })\n\n        return sorted(alerts, key=lambda x: x['score'], reverse=True)\n\n    def process_zeek_dns_log(self, log_path):\n        \"\"\"Process Zeek dns.log file.\"\"\"\n        with open(log_path, 'r') as f:\n            for line in f:\n                if line.startswith('#'):\n                    continue\n                fields = line.strip().split('\\t')\n                if len(fields) \u003C 22:\n                    continue\n                try:\n                    ts = datetime.fromtimestamp(float(fields[0]))\n                    src_ip = fields[2]\n                    query = fields[9]\n                    qtype = fields[11]\n                    self.process_query(ts, src_ip, query, qtype)\n                except (ValueError, IndexError):\n                    continue\n\n    def process_eve_json(self, log_path):\n        \"\"\"Process Suricata EVE JSON DNS log.\"\"\"\n        with open(log_path, 'r') as f:\n            for line in f:\n                try:\n                    event = json.loads(line)\n                    if event.get('event_type') != 'dns':\n                        continue\n                    dns = event.get('dns', {})\n                    ts = datetime.fromisoformat(event['timestamp'].replace('Z', '+00:00'))\n                    src_ip = event.get('src_ip', '')\n                    query = dns.get('rrname', '')\n                    qtype = dns.get('rrtype', '')\n                    self.process_query(ts, src_ip, query, qtype)\n                except (json.JSONDecodeError, KeyError, ValueError):\n                    continue\n\n\ndef main():\n    detector = DNSExfiltrationDetector()\n\n    log_file = sys.argv[1] if len(sys.argv) > 1 else '\u002Fopt\u002Fzeek\u002Flogs\u002Fcurrent\u002Fdns.log'\n\n    if log_file.endswith('.json'):\n        detector.process_eve_json(log_file)\n    else:\n        detector.process_zeek_dns_log(log_file)\n\n    alerts = detector.analyze()\n\n    if alerts:\n        print(f\"\\n{'='*80}\")\n        print(f\"DNS EXFILTRATION DETECTION RESULTS - {len(alerts)} suspicious domains found\")\n        print(f\"{'='*80}\\n\")\n\n        for alert in alerts:\n            severity = \"CRITICAL\" if alert['score'] >= 80 else \"HIGH\" if alert['score'] >= 60 else \"MEDIUM\"\n            print(f\"[{severity}] Domain: {alert['domain']}\")\n            print(f\"  Score: {alert['score']}\u002F100\")\n            print(f\"  Queries: {alert['query_count']}, Unique Subdomains: {alert['unique_subdomains']}\")\n            print(f\"  Avg Subdomain Length: {alert['avg_subdomain_length']}, Avg Entropy: {alert['avg_entropy']}\")\n            print(f\"  Source IPs: {', '.join(alert['source_ips'][:5])}\")\n            print(f\"  Indicators: {', '.join(alert['indicators'])}\")\n            print()\n    else:\n        print(\"No DNS exfiltration indicators detected.\")\n\n\nif __name__ == '__main__':\n    main()\n```\n\n### Step 3: Deploy Suricata Rules for DNS Exfiltration\n\n```\n# Detect long DNS queries (potential tunneling)\nalert dns $HOME_NET any -> any 53 (msg:\"DNS Exfiltration - Excessive query length\"; dns.query; content:\".\"; pcre:\"\u002F^.{60,}\u002F\"; threshold:type both,track by_src,count 20,seconds 60; classtype:bad-unknown; sid:3000001; rev:1;)\n\n# Detect high-entropy DNS subdomain\nalert dns $HOME_NET any -> any 53 (msg:\"DNS Exfiltration - High entropy subdomain\"; dns.query; pcre:\"\u002F^[a-zA-Z0-9+\\\u002F=]{30,}\\.\u002F\"; threshold:type both,track by_src,count 10,seconds 60; classtype:bad-unknown; sid:3000002; rev:1;)\n\n# Detect large TXT record responses\nalert dns any 53 -> $HOME_NET any (msg:\"DNS Exfiltration - Large TXT response\"; content:\"|00 10|\"; byte_test:2,>,400,0,relative; classtype:bad-unknown; sid:3000003; rev:1;)\n\n# Detect NULL record queries (used by iodine)\nalert dns $HOME_NET any -> any 53 (msg:\"DNS Exfiltration - NULL record query (iodine indicator)\"; content:\"|00 0a|\"; classtype:bad-unknown; sid:3000004; rev:1;)\n\n# Detect dnscat2 traffic pattern\nalert dns $HOME_NET any -> any 53 (msg:\"DNS Exfiltration - dnscat2 indicator\"; dns.query; content:\"dnscat\"; nocase; classtype:trojan-activity; sid:3000005; rev:1;)\n```\n\n### Step 4: SIEM Detection Rules\n\n**Splunk SPL query for DNS exfiltration:**\n\n```spl\nindex=dns sourcetype=zeek:dns\n| eval subdomain=mvindex(split(query,\".\"),0)\n| eval subdomain_len=len(subdomain)\n| eval label_count=mvcount(split(query,\".\"))\n| stats count as query_count,\n        dc(subdomain) as unique_subdomains,\n        avg(subdomain_len) as avg_sub_len,\n        values(src_ip) as source_ips\n        by query_domain\n| where query_count > 100 AND avg_sub_len > 30 AND unique_subdomains > 50\n| eval risk_score = case(\n    avg_sub_len > 50 AND unique_subdomains > 200, \"Critical\",\n    avg_sub_len > 40 AND unique_subdomains > 100, \"High\",\n    avg_sub_len > 30 AND unique_subdomains > 50, \"Medium\",\n    true(), \"Low\")\n| sort -query_count\n| table query_domain risk_score query_count unique_subdomains avg_sub_len source_ips\n```\n\n## Response Actions\n\n1. **Block the tunnel domain** at DNS resolver and firewall level\n2. **Isolate the source host** from the network for forensic investigation\n3. **Capture full PCAP** of the DNS traffic for evidence preservation\n4. **Identify exfiltrated data** by decoding captured DNS queries\n5. **Check for persistence** mechanisms on the compromised host\n6. **Update blocklists** with identified C2 domains and infrastructure\n\n## Best Practices\n\n- **DNS Logging** - Enable full DNS query and response logging at resolvers and network level\n- **Internal DNS Only** - Force all DNS through internal resolvers; block direct external DNS (port 53)\n- **Response Policy Zones** - Deploy RPZ feeds to block known tunneling domains\n- **Baseline First** - Establish normal DNS query patterns before setting detection thresholds\n- **TXT Record Monitoring** - Pay special attention to TXT and NULL record queries\n- **Encrypted DNS Awareness** - Monitor for DoH\u002FDoT usage that may bypass DNS inspection\n\n## References\n\n- [Splunk DNS Exfiltration Detection with Deep Learning](https:\u002F\u002Fwww.splunk.com\u002Fen_us\u002Fblog\u002Fsecurity\u002Fmachine-learning-in-security-detect-dns-data-exfiltration-using-deep-learning.html)\n- [Akamai DNS Data Exfiltration](https:\u002F\u002Fwww.akamai.com\u002Fglossary\u002Fwhat-is-dns-data-exfiltration)\n- [SANS Detecting DNS Tunneling](https:\u002F\u002Fwww.giac.org\u002Fpaper\u002Fgcia\u002F1116\u002Fdetecting-dns-tunneling\u002F108367)\n- [Fidelis DNS Tunneling Detection](https:\u002F\u002Ffidelissecurity.com\u002Fthreatgeek\u002Flearn\u002Fdns-tunneling-detection\u002F)\n","# Detecting DNS Exfiltration with DNS Query Analysis\n\n## Overview\n\nDNS exfiltration exploits the Domain Name System as a covert channel to extract data from compromised networks. Attackers encode stolen data into DNS query names (subdomains) or DNS response records (TXT, CNAME, NULL), bypassing traditional security controls that typically allow DNS traffic unrestricted. Tools like iodine, dnscat2, and dns2tcp enable full TCP tunneling over DNS. Detection requires analyzing DNS query patterns for anomalies including excessive query length, high entropy subdomain strings, abnormal query volumes to single domains, and oversized TXT record responses. This skill covers building a comprehensive DNS exfiltration detection capability using passive DNS analysis, statistical methods, and machine learning approaches.\n\n\n## When to Use\n\n- When investigating security incidents that require detecting dns exfiltration with dns query analysis\n- When building detection rules or threat hunting queries for this domain\n- When SOC analysts need structured procedures for this analysis type\n- When validating security monitoring coverage for related attack techniques\n\n## Prerequisites\n\n- Access to DNS query logs (passive DNS capture, DNS server logs, or PCAP)\n- Zeek, Suricata, or tcpdump for DNS traffic capture\n- Python 3.8+ with scipy, numpy, pandas, and scikit-learn\n- SIEM platform for alert correlation\n- Baseline of normal DNS traffic patterns for the environment\n\n## Core Concepts\n\n### DNS Tunneling Mechanics\n\nDNS exfiltration encodes data in different parts of DNS messages:\n\n**Outbound (Query-based exfiltration):**\n```\nEncoded data as subdomain labels:\ndGhlIHNlY3JldCBkYXRh.exfil.attacker.com\n[base64-encoded data].[tunnel domain]\n\nQuery types used: A, AAAA, CNAME, MX, TXT, NULL\n```\n\n**Inbound (Response-based command channel):**\n```\nTXT records carry encoded commands\u002Fdata in responses\nCNAME records chain encoded data through multiple labels\nNULL records carry arbitrary binary data\n```\n\n### Detection Indicators\n\n| Indicator | Normal DNS | DNS Tunneling |\n|-----------|-----------|---------------|\n| Subdomain length | 5-20 chars | 40-253 chars |\n| Label count | 2-4 labels | 5-10+ labels |\n| Shannon entropy | 2.5-3.5 bits | 4.0-5.5 bits |\n| Query volume (per domain) | Variable | 100s-1000s\u002Fmin |\n| TXT response size | \u003C 100 bytes | 200-4000+ bytes |\n| Unique subdomains | Low | Very high |\n| Query type distribution | Mostly A\u002FAAAA | Heavy TXT, NULL, CNAME |\n\n### Common Tunneling Tools\n\n| Tool | Protocol | Encoding | Detection Difficulty |\n|------|----------|----------|---------------------|\n| iodine | IP-over-DNS | Base32\u002FBase64\u002FRaw | Medium |\n| dnscat2 | TCP-over-DNS | Hex encoding | Medium |\n| dns2tcp | TCP-over-DNS | Base64 | Medium |\n| DNSExfiltrator | Custom | Base64 | Low |\n| Cobalt Strike DNS | C2 over DNS | Custom encoding | High |\n\n## Workflow\n\n### Step 1: Capture DNS Traffic\n\n**Using Zeek:**\n```bash\n# Live capture\nzeek -i eth0 -C base\u002Fprotocols\u002Fdns\n\n# Offline PCAP analysis\nzeek -r traffic.pcap base\u002Fprotocols\u002Fdns\n\n# Output: dns.log with query, qtype, answers, TTL\n```\n\n**Using tcpdump:**\n```bash\n# Capture all DNS traffic\ntcpdump -i eth0 -w dns_capture.pcap port 53\n\n# Capture with size filter (large DNS packets)\ntcpdump -i eth0 -w large_dns.pcap 'port 53 and greater 512'\n```\n\n**Using Suricata:**\n```yaml\n# In suricata.yaml, enable DNS logging\noutputs:\n  - eve-log:\n      types:\n        - dns:\n            query: yes\n            answer: yes\n            formats: [detailed]\n```\n\n### Step 2: Analyze Query Characteristics\n\nPython script for DNS exfiltration detection:\n\n```python\n#!\u002Fusr\u002Fbin\u002Fenv python3\n\"\"\"DNS Exfiltration Detector - Analyzes DNS logs for tunneling indicators.\"\"\"\n\nimport json\nimport math\nimport re\nimport sys\nfrom collections import defaultdict\nfrom datetime import datetime, timedelta\n\nimport pandas as pd\n\n\ndef calculate_entropy(domain: str) -> float:\n    \"\"\"Calculate Shannon entropy of a string.\"\"\"\n    if not domain:\n        return 0.0\n    freq = defaultdict(int)\n    for char in domain:\n        freq[char] += 1\n    length = len(domain)\n    entropy = -sum(\n        (count \u002F length) * math.log2(count \u002F length)\n        for count in freq.values()\n    )\n    return entropy\n\n\ndef extract_subdomain(query: str) -> str:\n    \"\"\"Extract subdomain portion from FQDN.\"\"\"\n    parts = query.rstrip('.').split('.')\n    if len(parts) > 2:\n        return '.'.join(parts[:-2])\n    return ''\n\n\ndef get_base_domain(query: str) -> str:\n    \"\"\"Extract registered domain from FQDN.\"\"\"\n    parts = query.rstrip('.').split('.')\n    if len(parts) >= 2:\n        return '.'.join(parts[-2:])\n    return query\n\n\ndef is_base64_like(s: str) -> bool:\n    \"\"\"Check if string resembles base64 encoding.\"\"\"\n    b64_chars = set('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+\u002F=')\n    if len(s) \u003C 10:\n        return False\n    char_ratio = sum(1 for c in s if c in b64_chars) \u002F len(s)\n    return char_ratio > 0.9 and calculate_entropy(s) > 4.0\n\n\ndef is_hex_encoded(s: str) -> bool:\n    \"\"\"Check if string appears hex-encoded.\"\"\"\n    hex_chars = set('0123456789abcdefABCDEF')\n    if len(s) \u003C 16:\n        return False\n    clean = s.replace('.', '').replace('-', '')\n    return all(c in hex_chars for c in clean) and len(clean) % 2 == 0\n\n\nclass DNSExfiltrationDetector:\n    def __init__(self):\n        self.domain_stats = defaultdict(lambda: {\n            'query_count': 0,\n            'unique_subdomains': set(),\n            'total_subdomain_length': 0,\n            'entropy_sum': 0.0,\n            'query_types': defaultdict(int),\n            'source_ips': set(),\n            'first_seen': None,\n            'last_seen': None,\n            'txt_response_sizes': [],\n        })\n\n        # Detection thresholds\n        self.thresholds = {\n            'min_query_count': 50,\n            'min_unique_subdomains': 30,\n            'avg_subdomain_length': 30,\n            'avg_entropy': 3.8,\n            'unique_ratio': 0.7,\n            'txt_query_ratio': 0.3,\n            'max_label_length': 63,\n            'max_subdomain_labels': 5,\n        }\n\n    def process_query(self, timestamp, src_ip, query, qtype, response_size=0):\n        \"\"\"Process a single DNS query and update statistics.\"\"\"\n        base_domain = get_base_domain(query)\n        subdomain = extract_subdomain(query)\n\n        stats = self.domain_stats[base_domain]\n        stats['query_count'] += 1\n        stats['unique_subdomains'].add(subdomain)\n        stats['total_subdomain_length'] += len(subdomain)\n        stats['entropy_sum'] += calculate_entropy(subdomain)\n        stats['query_types'][qtype] += 1\n        stats['source_ips'].add(src_ip)\n\n        if stats['first_seen'] is None:\n            stats['first_seen'] = timestamp\n        stats['last_seen'] = timestamp\n\n        if qtype in ('TXT', 'NULL') and response_size > 0:\n            stats['txt_response_sizes'].append(response_size)\n\n    def analyze(self):\n        \"\"\"Analyze accumulated statistics and return suspicious domains.\"\"\"\n        alerts = []\n\n        for domain, stats in self.domain_stats.items():\n            if stats['query_count'] \u003C self.thresholds['min_query_count']:\n                continue\n\n            unique_count = len(stats['unique_subdomains'])\n            avg_length = stats['total_subdomain_length'] \u002F stats['query_count']\n            avg_entropy = stats['entropy_sum'] \u002F stats['query_count']\n            unique_ratio = unique_count \u002F stats['query_count']\n\n            txt_queries = stats['query_types'].get('TXT', 0) + stats['query_types'].get('NULL', 0)\n            txt_ratio = txt_queries \u002F stats['query_count']\n\n            score = 0\n            indicators = []\n\n            if avg_length > self.thresholds['avg_subdomain_length']:\n                score += 25\n                indicators.append(f\"high_avg_subdomain_length={avg_length:.1f}\")\n\n            if avg_entropy > self.thresholds['avg_entropy']:\n                score += 25\n                indicators.append(f\"high_entropy={avg_entropy:.2f}\")\n\n            if unique_ratio > self.thresholds['unique_ratio']:\n                score += 20\n                indicators.append(f\"high_unique_ratio={unique_ratio:.2f}\")\n\n            if txt_ratio > self.thresholds['txt_query_ratio']:\n                score += 15\n                indicators.append(f\"high_txt_ratio={txt_ratio:.2f}\")\n\n            if unique_count > self.thresholds['min_unique_subdomains']:\n                score += 15\n                indicators.append(f\"unique_subdomains={unique_count}\")\n\n            # Check for encoding patterns\n            encoded_count = sum(\n                1 for sd in list(stats['unique_subdomains'])[:100]\n                if is_base64_like(sd) or is_hex_encoded(sd)\n            )\n            if encoded_count > 20:\n                score += 20\n                indicators.append(f\"encoded_subdomains={encoded_count}\")\n\n            if score >= 50:\n                duration = (stats['last_seen'] - stats['first_seen']).total_seconds() if stats['first_seen'] and stats['last_seen'] else 0\n                alerts.append({\n                    'domain': domain,\n                    'score': min(score, 100),\n                    'query_count': stats['query_count'],\n                    'unique_subdomains': unique_count,\n                    'avg_subdomain_length': round(avg_length, 1),\n                    'avg_entropy': round(avg_entropy, 2),\n                    'unique_ratio': round(unique_ratio, 2),\n                    'txt_ratio': round(txt_ratio, 2),\n                    'source_ips': list(stats['source_ips']),\n                    'duration_seconds': duration,\n                    'indicators': indicators,\n                })\n\n        return sorted(alerts, key=lambda x: x['score'], reverse=True)\n\n    def process_zeek_dns_log(self, log_path):\n        \"\"\"Process Zeek dns.log file.\"\"\"\n        with open(log_path, 'r') as f:\n            for line in f:\n                if line.startswith('#'):\n                    continue\n                fields = line.strip().split('\\t')\n                if len(fields) \u003C 22:\n                    continue\n                try:\n                    ts = datetime.fromtimestamp(float(fields[0]))\n                    src_ip = fields[2]\n                    query = fields[9]\n                    qtype = fields[11]\n                    self.process_query(ts, src_ip, query, qtype)\n                except (ValueError, IndexError):\n                    continue\n\n    def process_eve_json(self, log_path):\n        \"\"\"Process Suricata EVE JSON DNS log.\"\"\"\n        with open(log_path, 'r') as f:\n            for line in f:\n                try:\n                    event = json.loads(line)\n                    if event.get('event_type') != 'dns':\n                        continue\n                    dns = event.get('dns', {})\n                    ts = datetime.fromisoformat(event['timestamp'].replace('Z', '+00:00'))\n                    src_ip = event.get('src_ip', '')\n                    query = dns.get('rrname', '')\n                    qtype = dns.get('rrtype', '')\n                    self.process_query(ts, src_ip, query, qtype)\n                except (json.JSONDecodeError, KeyError, ValueError):\n                    continue\n\n\ndef main():\n    detector = DNSExfiltrationDetector()\n\n    log_file = sys.argv[1] if len(sys.argv) > 1 else '\u002Fopt\u002Fzeek\u002Flogs\u002Fcurrent\u002Fdns.log'\n\n    if log_file.endswith('.json'):\n        detector.process_eve_json(log_file)\n    else:\n        detector.process_zeek_dns_log(log_file)\n\n    alerts = detector.analyze()\n\n    if alerts:\n        print(f\"\\n{'='*80}\")\n        print(f\"DNS EXFILTRATION DETECTION RESULTS - {len(alerts)} suspicious domains found\")\n        print(f\"{'='*80}\\n\")\n\n        for alert in alerts:\n            severity = \"CRITICAL\" if alert['score'] >= 80 else \"HIGH\" if alert['score'] >= 60 else \"MEDIUM\"\n            print(f\"[{severity}] Domain: {alert['domain']}\")\n            print(f\"  Score: {alert['score']}\u002F100\")\n            print(f\"  Queries: {alert['query_count']}, Unique Subdomains: {alert['unique_subdomains']}\")\n            print(f\"  Avg Subdomain Length: {alert['avg_subdomain_length']}, Avg Entropy: {alert['avg_entropy']}\")\n            print(f\"  Source IPs: {', '.join(alert['source_ips'][:5])}\")\n            print(f\"  Indicators: {', '.join(alert['indicators'])}\")\n            print()\n    else:\n        print(\"No DNS exfiltration indicators detected.\")\n\n\nif __name__ == '__main__':\n    main()\n```\n\n### Step 3: Deploy Suricata Rules for DNS Exfiltration\n\n```\n# Detect long DNS queries (potential tunneling)\nalert dns $HOME_NET any -> any 53 (msg:\"DNS Exfiltration - Excessive query length\"; dns.query; content:\".\"; pcre:\"\u002F^.{60,}\u002F\"; threshold:type both,track by_src,count 20,seconds 60; classtype:bad-unknown; sid:3000001; rev:1;)\n\n# Detect high-entropy DNS subdomain\nalert dns $HOME_NET any -> any 53 (msg:\"DNS Exfiltration - High entropy subdomain\"; dns.query; pcre:\"\u002F^[a-zA-Z0-9+\\\u002F=]{30,}\\.\u002F\"; threshold:type both,track by_src,count 10,seconds 60; classtype:bad-unknown; sid:3000002; rev:1;)\n\n# Detect large TXT record responses\nalert dns any 53 -> $HOME_NET any (msg:\"DNS Exfiltration - Large TXT response\"; content:\"|00 10|\"; byte_test:2,>,400,0,relative; classtype:bad-unknown; sid:3000003; rev:1;)\n\n# Detect NULL record queries (used by iodine)\nalert dns $HOME_NET any -> any 53 (msg:\"DNS Exfiltration - NULL record query (iodine indicator)\"; content:\"|00 0a|\"; classtype:bad-unknown; sid:3000004; rev:1;)\n\n# Detect dnscat2 traffic pattern\nalert dns $HOME_NET any -> any 53 (msg:\"DNS Exfiltration - dnscat2 indicator\"; dns.query; content:\"dnscat\"; nocase; classtype:trojan-activity; sid:3000005; rev:1;)\n```\n\n### Step 4: SIEM Detection Rules\n\n**Splunk SPL query for DNS exfiltration:**\n\n```spl\nindex=dns sourcetype=zeek:dns\n| eval subdomain=mvindex(split(query,\".\"),0)\n| eval subdomain_len=len(subdomain)\n| eval label_count=mvcount(split(query,\".\"))\n| stats count as query_count,\n        dc(subdomain) as unique_subdomains,\n        avg(subdomain_len) as avg_sub_len,\n        values(src_ip) as source_ips\n        by query_domain\n| where query_count > 100 AND avg_sub_len > 30 AND unique_subdomains > 50\n| eval risk_score = case(\n    avg_sub_len > 50 AND unique_subdomains > 200, \"Critical\",\n    avg_sub_len > 40 AND unique_subdomains > 100, \"High\",\n    avg_sub_len > 30 AND unique_subdomains > 50, \"Medium\",\n    true(), \"Low\")\n| sort -query_count\n| table query_domain risk_score query_count unique_subdomains avg_sub_len source_ips\n```\n\n## Response Actions\n\n1. **Block the tunnel domain** at DNS resolver and firewall level\n2. **Isolate the source host** from the network for forensic investigation\n3. **Capture full PCAP** of the DNS traffic for evidence preservation\n4. **Identify exfiltrated data** by decoding captured DNS queries\n5. **Check for persistence** mechanisms on the compromised host\n6. **Update blocklists** with identified C2 domains and infrastructure\n\n## Best Practices\n\n- **DNS Logging** - Enable full DNS query and response logging at resolvers and network level\n- **Internal DNS Only** - Force all DNS through internal resolvers; block direct external DNS (port 53)\n- **Response Policy Zones** - Deploy RPZ feeds to block known tunneling domains\n- **Baseline First** - Establish normal DNS query patterns before setting detection thresholds\n- **TXT Record Monitoring** - Pay special attention to TXT and NULL record queries\n- **Encrypted DNS Awareness** - Monitor for DoH\u002FDoT usage that may bypass DNS inspection\n\n## References\n\n- [Splunk DNS Exfiltration Detection with Deep Learning](https:\u002F\u002Fwww.splunk.com\u002Fen_us\u002Fblog\u002Fsecurity\u002Fmachine-learning-in-security-detect-dns-data-exfiltration-using-deep-learning.html)\n- [Akamai DNS Data Exfiltration](https:\u002F\u002Fwww.akamai.com\u002Fglossary\u002Fwhat-is-dns-data-exfiltration)\n- [SANS Detecting DNS Tunneling](https:\u002F\u002Fwww.giac.org\u002Fpaper\u002Fgcia\u002F1116\u002Fdetecting-dns-tunneling\u002F108367)\n- [Fidelis DNS Tunneling Detection](https:\u002F\u002Ffidelissecurity.com\u002Fthreatgeek\u002Flearn\u002Fdns-tunneling-detection\u002F)\n",{"name":5,"tags":49,"author":51,"domain":43,"license":15,"version":52,"nist_csf":53,"subdomain":33,"description":7,"mitre_attack":58},[31,39,37,38,30,50,32,29,28],"passive-dns","mahipal","1.0",[54,55,56,57],"PR.IR-01","DE.CM-01","ID.AM-03","PR.DS-02",[59,60,61,62,63],"T1046","T1040","T1557","T1071","T1048","main","54a798831d2266a3ca61ce68a7acb80b81160d57","skills\u002Fdetecting-dns-exfiltration-with-dns-query-analysis",4414,"https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills","https:\u002F\u002Fmahipal.engineer\u002FAnthropic-Cybersecurity-Skills\u002F","https:\u002F\u002Fgithub.com\u002Fmukul975","Mahipal.engineer","🔐 Cybersecurity | 💻 Dev | 📷 Street Photographer\r\n🎓 MSc | 📚 Research & AI Security","2026-08-31 12:32:44",{"source":8,"skillName":5,"commands":75,"prompt":85,"zipAvailable":86},[76,79,82],{"tool":77,"command":78},"npx","npx skills add mukul975\u002FAnthropic-Cybersecurity-Skills --skill detecting-dns-exfiltration-with-dns-query-analysis",{"tool":80,"command":81},"bunx","bunx skills add mukul975\u002FAnthropic-Cybersecurity-Skills --skill detecting-dns-exfiltration-with-dns-query-analysis",{"tool":83,"command":84},"pnpm","pnpm dlx skills add mukul975\u002FAnthropic-Cybersecurity-Skills --skill detecting-dns-exfiltration-with-dns-query-analysis","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fdetecting-dns-exfiltration-with-dns-query-analysis\u002FSKILL.md",true,[88,93,99],{"path":89,"resourceType":89,"resourceTypeDesc":90,"sizeBytes":91,"sourceHtmlUrl":92},"LICENSE","许可证",11255,"https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fdetecting-dns-exfiltration-with-dns-query-analysis\u002FLICENSE",{"path":94,"resourceType":95,"resourceTypeDesc":96,"sizeBytes":97,"sourceHtmlUrl":98},"references\u002Fapi-reference.md","REFERENCE","参考文档",1525,"https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fdetecting-dns-exfiltration-with-dns-query-analysis\u002Freferences\u002Fapi-reference.md",{"path":100,"resourceType":101,"resourceTypeDesc":102,"sizeBytes":103,"sourceHtmlUrl":104},"scripts\u002Fagent.py","SCRIPT","脚本",6114,"https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fdetecting-dns-exfiltration-with-dns-query-analysis\u002Fscripts\u002Fagent.py",[106,131,155,183,208,235],{"skillNo":107,"name":108,"nameZh":6,"description":109,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":110,"categories":111,"keywords":113,"publishedAt":44},"01M6AGDM3HJXTKXX15ZZ0ZVCJ3","verifying-build-provenance-with-slsa-sigstore","Verifies artifact signatures and SLSA provenance using Sigstore's cosign (verify, verify-attestation, verify-blob-attestation) and slsa-verifier (verify-artifact), enforcing keyless OIDC builder identity and source repo against SLSA Build levels. Use in CI\u002FCD before deploying artifacts, when consuming third-party attestations, establishing a SLSA Build L3 pipeline, or confirming provenance during incident response or admission control.","https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fverifying-build-provenance-with-slsa-sigstore\u002FSKILL.md",[112],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[114,115,116,117,36,43,118,119,41,120,121,122,123,124,125,126,127,128,129,130],"sigstore","provenance","slsa","verifying build provenance with slsa sigstore","incident response","identity","code","artifacts","ci","supply-chain","pipeline","supply-chain-security","t1195","attestation","code-signing","cosign","keyless",{"skillNo":132,"name":133,"nameZh":6,"description":134,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":135,"categories":136,"keywords":138,"publishedAt":44},"01M6AGDGBPWYVZ2F11GFKJ4HZ9","validating-tpm-measured-boot-attestation","Verifies TPM 2.0 measured-boot integrity and remote attestation with tpm2-tools -- reading PCRs (tpm2_pcrread), replaying the boot event log, generating and checking signed quotes (tpm2_quote\u002Ftpm2_checkquote), and sealing secrets to a PCR policy. Use to confirm a system booted trusted firmware\u002Fkernel for Zero Trust device posture, detect boot-chain tampering via PCR drift, or build a golden-value baseline for fleet attestation.","https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fvalidating-tpm-measured-boot-attestation\u002FSKILL.md",[137],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[139,127,140,141,36,142,43,41,143,144,145,146,147,148,149,150,151,152,153,154],"boot","TPM","validating tpm measured boot attestation","policy","verification","ZeRO","firmware","Tools","measured-boot","PCR","integrity","secrets","remote-attestation","tpm2-tools","integrity-verification","trusted-computing",{"skillNo":156,"name":157,"nameZh":6,"description":158,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":159,"categories":160,"keywords":165,"publishedAt":44},"01M6AGDCW0Y4FXZ3362GT1941M","validating-backup-integrity-for-recovery","Validates backup integrity through cryptographic hash verification, automated restore testing, corruption detection, and recoverability checks to confirm backups are reliable for disaster recovery and ransomware response. Use before relying on backups for recovery, when building post-backup validation pipelines, auditing backup infrastructure for compliance, or checking immutable\u002Fair-gapped backups for silent corruption or tampering.","https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fvalidating-backup-integrity-for-recovery\u002FSKILL.md",[161,164],{"categoryNo":162,"categoryName":163,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[149,166,167,168,169,43,170,171,143,172,173,174,175,176,177,178,179,180,181,182],"backup","recovery","validating backup integrity for recovery","testing","infrastructure","validation","compliance","hash-verification","incident-response","ransomware","cryptocurrency","detection","t1078","t1490","immutable","disaster-recovery","restore-testing",{"skillNo":184,"name":185,"nameZh":6,"description":186,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":187,"categories":188,"keywords":190,"publishedAt":44},"01M6AGD9GBG2KZ336AE763J3WH","triaging-windows-with-kape","Runs KAPE (Kroll Artifact Parser and Extractor) to collect targeted forensic artifacts (registry hives, $MFT, event logs, prefetch, browser data) via Targets and parse them with Modules wrapping Eric Zimmerman's EZ Tools (PECmd, MFTECmd, RECmd). Use during early incident containment\u002Ftriage when full disk imaging is impractical but a defensible, parseable Windows artifact set is needed quickly, including at-scale remote collection.","https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Ftriaging-windows-with-kape\u002FSKILL.md",[189],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[191,192,193,43,194,195,196,197,198,199,200,34,201,202,203,204,146,205,206,207],"windows","kape","triaging windows with kape","registry","browser","logs","windows-forensics","dfir","mft","mftecmd","prefetch","eric-zimmerman","digital-forensics","SET","collection","pecmd","artifact-collection",{"skillNo":209,"name":210,"nameZh":6,"description":211,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":212,"categories":213,"keywords":215,"publishedAt":44},"01M6AGD5PW5J4EVZM958WD74ZQ","triaging-vulnerabilities-with-ssvc-framework","Triages and prioritizes vulnerabilities with CISA's Stakeholder-Specific Vulnerability Categorization (SSVC) decision tree, weighing exploitation status (via the CISA KEV catalog and FIRST EPSS API), technical impact, automatability, and mission prevalence to output Track\u002FTrack*\u002FAttend\u002FAct decisions. Use when prioritizing vulnerability scan results (OpenVAS, Nessus, Qualys) for remediation planning beyond raw CVSS scores.","https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Ftriaging-vulnerabilities-with-ssvc-framework\u002FSKILL.md",[214],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[216,217,218,43,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234],"vulnerabilities","framework","triaging vulnerabilities with ssvc framework","status","planning","CISA","vulnerability-management","risk-management","nessus","qualys","openvas","cvss","remediation","risk","vulnerability","api","prioritization","ssvc","decision-tree",{"skillNo":236,"name":237,"nameZh":6,"description":238,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":239,"categories":240,"keywords":242,"publishedAt":44},"01M6AGD24TTQQM4CXG69E3B9TJ","triaging-security-incident","Performs initial triage of security incidents using the NIST SP 800-61r3 and SANS PICERL frameworks, classifying incident type, assigning priority by business impact, and routing to the appropriate response team. Use when a SIEM\u002FEDR alert needs human classification, concurrent alerts must be prioritized, or a user report or threat-intel IOC match requires initial incident categorization.","https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Ftriaging-security-incident\u002FSKILL.md",[241],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[36,243,43,244,245,246,247,248,249,250,251,178,252,179,253,254,255,256,257,258],"triaging security incident","siem","file","ioc","soc","NIST-800-61","NIST","severity","edr","execution","analysis","classification","severity-classification","incident-triage","SANS-PICERL","SOC-operations"]