L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Explorer les Skills
Productivité · SKILL.md

analyzing-dns-logs-for-exfiltration

analyzing-dns-logs-for-exfiltration

分析 DNS 查询日志,利用熵值分析、查询量异常检测和子域名长度检测,在 SIEM 平台中检测 DNS 隧道数据外泄、DGA 域名通信和隐蔽 C2 信道。适用于 SOC 团队识别绕过传统网络安全控制的 DNS 威胁。

Independent GitHub snapshot · Automated classification · Original documentation governs

Documentation de la Skill

GitHub

name: analyzing-dns-logs-for-exfiltration description: > 分析 DNS 查询日志,利用熵值分析、查询量异常检测和子域名长度检测,在 SIEM 平台中检测 DNS 隧道数据外泄、DGA 域名通信和隐蔽 C2 信道。适用于 SOC 团队识别绕过传统网络安全控制的 DNS 威胁。 domain: cybersecurity subdomain: soc-operations tags: [soc, dns, exfiltration, dns-tunneling, dga, c2-detection, splunk, threat-detection] version: "1.0" author: mahipal license: Apache-2.0

分析 DNS 日志中的数据外泄

适用场景

在以下情况下使用本技能:

  • SOC 团队怀疑通过 DNS 隧道进行数据外泄以绕过防火墙/代理控制
  • 威胁情报显示对手使用基于 DNS 的 C2 信道(例如 Cobalt Strike DNS Beacon)
  • UEBA 检测到特定主机存在异常 DNS 查询量
  • 恶意软件分析揭示具有 DNS-over-HTTPS(DoH)或 DNS 隧道能力

不适用于标准 DNS 故障排除或可用性监控——本技能专注于与安全相关的 DNS 滥用检测。

前置条件

  • 已启用 DNS 查询日志记录(Windows DNS Server、Bind、Infoblox 或 Cisco Umbrella)
  • DNS 日志已摄取到 SIEM(Splunk 的 Stream:DNS、dns 数据源或 Zeek DNS 日志)
  • 用于历史域名解析分析的被动 DNS 数据
  • 正常 DNS 行为基线(查询量、域名分布、TXT 记录频率)
  • Python(含 math 和 collections 库)用于熵值计算

工作流程

步骤 1:通过子域名长度分析检测 DNS 隧道

DNS 隧道将数据编码在子域名标签中,产生异常长的查询:

index=dns sourcetype="stream:dns" query_type IN ("A", "AAAA", "TXT", "CNAME", "MX")
| eval domain_parts = split(query, ".")
| eval subdomain = mvindex(domain_parts, 0, mvcount(domain_parts)-3)
| eval subdomain_str = mvjoin(subdomain, ".")
| eval subdomain_len = len(subdomain_str)
| eval tld = mvindex(domain_parts, -1)
| eval registered_domain = mvindex(domain_parts, -2).".".tld
| where subdomain_len > 50
| stats count AS queries, dc(query) AS unique_queries,
        avg(subdomain_len) AS avg_subdomain_len,
        max(subdomain_len) AS max_subdomain_len,
        values(src_ip) AS sources
  by registered_domain
| where queries > 20
| sort - avg_subdomain_len
| table registered_domain, queries, unique_queries, avg_subdomain_len, max_subdomain_len, sources

步骤 2:检测高熵域名查询(DGA 检测)

域名生成算法(DGA)产生看似随机的域名:

index=dns sourcetype="stream:dns"
| eval domain_parts = split(query, ".")
| eval sld = mvindex(domain_parts, -2)
| eval sld_len = len(sld)
| eval char_count = sld_len
| eval vowels = len(replace(sld, "[^aeiou]", ""))
| eval consonants = len(replace(sld, "[^bcdfghjklmnpqrstvwxyz]", ""))
| eval digits = len(replace(sld, "[^0-9]", ""))
| eval vowel_ratio = if(char_count > 0, vowels / char_count, 0)
| eval digit_ratio = if(char_count > 0, digits / char_count, 0)
| where sld_len > 12 AND (vowel_ratio < 0.2 OR digit_ratio > 0.3)
| stats count AS queries, dc(query) AS unique_domains, values(src_ip) AS sources
  by query
| where unique_domains > 10
| sort - queries

基于 Python 的 DNS 查询香农熵(Shannon Entropy)计算:

import math
from collections import Counter

def shannon_entropy(text):
    """计算字符串的香农熵"""
    if not text:
        return 0
    counter = Counter(text.lower())
    length = len(text)
    entropy = -sum(
        (count / length) * math.log2(count / length)
        for count in counter.values()
    )
    return round(entropy, 4)

# 测试示例
normal_domain = "google"           # 低熵
dga_domain = "x8kj2m9p4qw7n"      # 高熵
tunnel_subdomain = "aGVsbG8gd29ybGQ.evil.com"  # Base64 编码的数据

print(f"正常: {shannon_entropy(normal_domain)}")     # ~2.25
print(f"DGA:  {shannon_entropy(dga_domain)}")         # ~3.70
print(f"隧道: {shannon_entropy(tunnel_subdomain)}")   # ~3.50

# 阈值:子域名熵值 > 3.5 = 可能是隧道/DGA

Splunk 熵值评分实现:

index=dns sourcetype="stream:dns"
| eval domain_parts = split(query, ".")
| eval check_string = mvindex(domain_parts, 0)
| eval check_len = len(check_string)
| where check_len > 8
| eval chars = split(check_string, "")
| stats count AS total_chars, dc(chars) AS unique_chars by query, src_ip, check_string, check_len
| eval entropy_estimate = log(unique_chars, 2) * (unique_chars / check_len)
| where entropy_estimate > 3.5
| stats count AS high_entropy_queries, dc(query) AS unique_queries by src_ip
| where high_entropy_queries > 50
| sort - high_entropy_queries

步骤 3:检测异常 DNS 查询量

识别产生异常 DNS 流量的主机:

index=dns sourcetype="stream:dns" earliest=-24h
| bin _time span=1h
| stats count AS queries, dc(query) AS unique_domains by src_ip, _time
| eventstats avg(queries) AS avg_queries, stdev(queries) AS stdev_queries by src_ip
| eval z_score = (queries - avg_queries) / stdev_queries
| where z_score > 3 OR queries > 5000
| sort - z_score
| table _time, src_ip, queries, unique_domains, avg_queries, z_score

检测 TXT 记录滥用(常见隧道方法):

index=dns sourcetype="stream:dns" query_type="TXT"
| stats count AS txt_queries, dc(query) AS unique_txt_domains,
        values(query) AS domains by src_ip
| where txt_queries > 100
| eval suspicion = case(
    txt_queries > 1000, "CRITICAL — 可能是 DNS 隧道",
    txt_queries > 500, "HIGH — 可能是 DNS 隧道",
    txt_queries > 100, "MEDIUM — 异常 TXT 查询量"
  )
| sort - txt_queries
| table src_ip, txt_queries, unique_txt_domains, suspicion

步骤 4:检测已知 DNS 隧道工具

搜索常见 DNS 隧道工具的特征:

index=dns sourcetype="stream:dns"
| eval query_lower = lower(query)
| where (
    match(query_lower, "\.dnscat\.") OR
    match(query_lower, "\.dns2tcp\.") OR
    match(query_lower, "\.iodine\.") OR
    match(query_lower, "\.dnscapy\.") OR
    match(query_lower, "\.cobalt.*\.beacon") OR
    query_type="NULL" OR
    (query_type="TXT" AND len(query) > 100)
  )
| stats count by src_ip, query, query_type
| sort - count

检测 DNS over HTTPS(DoH)绕过本地 DNS:

index=proxy OR index=firewall
dest IN ("1.1.1.1", "1.0.0.1", "8.8.8.8", "8.8.4.4",
         "9.9.9.9", "149.112.112.112", "208.67.222.222")
dest_port=443
| stats sum(bytes_out) AS total_bytes, count AS connections by src_ip, dest
| where connections > 100 OR total_bytes > 10485760
| eval alert = "可能的 DoH 绕过 — 通过 HTTPS 将 DNS 查询发送到公共解析器"
| sort - total_bytes

步骤 5:将 DNS 发现与终端数据关联

将可疑 DNS 与进程数据进行交叉参考:

index=dns src_ip="192.168.1.105" query="*.evil-tunnel.com" earliest=-24h
| stats count AS dns_queries, earliest(_time) AS first_query, latest(_time) AS last_query
  by src_ip, query
| join src_ip [
    search index=sysmon EventCode=3 DestinationPort=53 Computer="WORKSTATION-042"
    | stats count AS connections, values(Image) AS processes by SourceIp
    | rename SourceIp AS src_ip
  ]
| table src_ip, query, dns_queries, first_query, last_query, processes

步骤 6:估算数据外泄量

估算 DNS 查询中编码数据的体积:

index=dns src_ip="192.168.1.105" query="*.evil-tunnel.com" earliest=-24h
| eval domain_parts = split(query, ".")
| eval encoded_data = mvindex(domain_parts, 0)
| eval encoded_bytes = len(encoded_data)
| eval decoded_bytes = encoded_bytes * 0.75  -- Base64 解码因子
| stats sum(decoded_bytes) AS total_bytes_estimated, count AS total_queries,
        earliest(_time) AS first_seen, latest(_time) AS last_seen
| eval estimated_kb = round(total_bytes_estimated / 1024, 1)
| eval estimated_mb = round(total_bytes_estimated / 1048576, 2)
| eval duration_hours = round((last_seen - first_seen) / 3600, 1)
| eval rate_kbps = round(estimated_kb / (duration_hours * 3600) * 8, 2)
| table total_queries, estimated_mb, duration_hours, rate_kbps, first_seen, last_seen

核心概念

术语定义
DNS 隧道将数据编码在 DNS 查询/响应中,通过 DNS 外泄数据或建立 C2 信道的技术
DGA域名生成算法——恶意软件技术,生成伪随机域名以提高 C2 韧性
香农熵字符串随机性的数学度量——域名中高熵(>3.5)表明存在 DGA 或隧道
TXT 记录滥用利用 DNS TXT 记录(设计用于文本数据)作为数据隧道的高带宽信道
DNS over HTTPS(DoH)通过 HTTPS(端口 443)加密的 DNS 查询,绕过传统 DNS 监控
被动 DNS历史 DNS 解析记录,显示某域名随时间解析到的 IP 地址

工具与系统

  • Splunk Stream:提供解析 DNS 查询数据的网络流量捕获插件,用于 SIEM 分析
  • Zeek(Bro):生成详细 DNS 事务日志的网络安全监视器
  • Cisco Umbrella(OpenDNS):云 DNS 安全平台,阻断恶意域名并记录查询数据
  • Infoblox DNS Firewall:提供基于 RPZ 阻断和详细查询日志的 DNS 层安全
  • Farsight DNSDB:被动 DNS 数据库,用于历史域名解析查询和基础设施映射

常见场景

  • Cobalt Strike DNS Beacon:检测向 C2 域定期发送含编码载荷的 TXT 查询
  • 数据外泄:大量唯一子域名查询,以 Base64/十六进制编码窃取的数据
  • DGA 恶意软件:检测对算法生成域名的 DNS 查询(高熵、无 Web 内容)
  • DNS-over-HTTPS 绕过:员工使用 DoH 绕过企业 DNS 过滤和监控
  • 慢速滴漏式外泄:低量 DNS 隧道保持在阈值告警以下(需要与基线比较)

输出格式

DNS 外泄分析 — WORKSTATION-042
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
时间段:      2024-03-14 至 2024-03-15
来源:        192.168.1.105(WORKSTATION-042,财务部门)

发现:
  [CRITICAL] 检测到 DNS 隧道至 evil-tunnel[.]com
    查询量:        18 小时内 12,847 次查询
    平均子域名长:  63 字符(正常值:<20)
    平均熵值:      3.82(阈值:3.5)
    查询类型:      TXT(89%)、A(11%)
    估算数据量:    约 4.7 MB 通过 DNS 外泄
    速率:          0.58 kbps(慢速滴漏模式)

  [HIGH] 已解析 DGA 类域名
    唯一 DGA 域名:  247 个域名已解析
    模式:          15 字符随机字母数字.xyz TLD
    熵值范围:      3.6 - 4.1

进程归因:
  进程:   svchost_update.exe(伪装——非合法 svchost)
  PID:    4892
  父进程:  explorer.exe
  哈希:   SHA256: a1b2c3d4...(VT: 34/72 恶意 — Cobalt Strike Beacon)

遏制措施:
  [已完成] 主机已通过 EDR 隔离
  [已完成] 域名 evil-tunnel[.]com 已添加到 DNS 沉洞
  [已完成] 事件 IR-2024-0448 已创建
Skills enregistrées