关于 hunting-for-dns-tunneling-with-zeek
面向安全分析人员的 Zeek DNS 隧道狩猎指南,用于调查经 DNS 进行的隐蔽通信和数据外传。它结合查询长度、子域熵、唯一子域数量、记录类型与时间模式分析。
主要功能
- 01分析 DNS 查询长度与分布
- 02计算子域熵和唯一数量
- 03检查 DNS 记录类型与流量
- 04分析查询时间模式
- 05关联 conn.log 与域名情报
适用场景
- 01调查疑似 DNS 数据外传
- 02排查高频或长子域查询
- 03狩猎 iodine、dnscat2 等隧道工具
- 04分析威胁情报提示的 DNS C2
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill hunting-for-dns-tunneling-with-zeek安装后在 Claude Code 中输入/hunting-for-dns-tunneling-with-zeek确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSEassets/template.mdreferences/api-reference.mdstandards.mdworkflows.mdscripts/agent.pyprocess.py详细介绍
使用 Zeek 猎捕 DNS 隧道
何时使用
- 在猎捕通过 DNS 隐蔽通道进行的数据外泄时
- 当威胁情报显示有针对你所在行业的基于 DNS 的 C2 框架时
- 当 dns.log 显示发往特定域名的查询量异常高时
- 在调查疑似数据窃取但未发现 HTTP/S 外泄时
- 在监控 iodine、dnscat2、DNSExfiltrator 或 DNS-over-HTTPS 隧道等工具时
前置条件
- Zeek 部署在网络分路器或 SPAN 端口上,捕获 DNS 流量
- Zeek dns.log 包含完整的查询和响应字段
- 用于 dns.log 分析的 SIEM 平台(Splunk、Elastic)
- 用于自动化 DNS 分析的 RITA(Real Intelligence Threat Analytics)
- 用于历史域名解析上下文的被动 DNS 数据
工作流
- 分析查询长度分布:DNS 隧道将数据编码在子域标签中,产生的查询明显长于正常查询。正常 DNS 查询平均为 20-30 个字符;隧道查询通常超过 50+ 个字符。按域名计算查询长度的均值和标准差。
- 计算子域熵:隧道使用 Base32/Base64 编码数据,产生高熵的子域字符串。计算子域标签的香农熵——高于 3.5 比特/字符的值强烈表明存在编码数据。
- 统计每个域名的唯一子域数量:合法域名的唯一子域相对较少。DNS 隧道会在单个父域名下生成数百或数千个唯一子域。
- 监控 DNS 记录类型分布:TXT、NULL、CNAME 和 MX 记录比 A 记录能携带更多数据。对单个域名的过多 TXT 查询表明通过 DNS 传输数据。
- 检测高查询量:标记单个来源每小时发送超过 100 次查询的域名,尤其是当同时存在高子域唯一性时。
- 分析查询时序:DNS 隧道工具产生规律的查询模式(信标)或突发模式(数据传输)。对 DNS 查询时间戳应用频率分析。
- 与 conn.log 交叉比对:将 DNS 查询与连接元数据关联,以识别生成可疑查询的进程或端点。
- 用域名情报验证:对照 WHOIS 数据、证书透明度和威胁情报源检查可疑域名。
关键概念
| 概念 | 描述 |
|---|---|
| T1071.004 | 应用层协议:DNS |
| T1048.003 | 通过替代协议外泄:DNS |
| T1572 | 协议隧道 |
| 香农熵 | 子域字符串随机性的度量 |
| Zeek dns.log | DNS 查询/响应元数据 |
| RITA | 基于 Zeek 日志的自动化 DNS 隧道检测 |
| iodine | IPv4-over-DNS 隧道工具 |
| dnscat2 | 基于 DNS 的命令与控制工具 |
| DNSExfiltrator | 使用 DNS 请求的数据外泄工具 |
检测查询
Zeek 脚本——DNS 隧道检测
@load base/protocols/dns
module DNSTunnel;
export {
redef enum Notice::Type += { DNSTunnel::Long_DNS_Query };
const query_length_threshold = 50 &redef;
const query_count_threshold = 100 &redef;
}
event dns_request(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count) {
if ( |query| > query_length_threshold ) {
NOTICE([$note=DNSTunnel::Long_DNS_Query,
$msg=fmt("Long DNS query detected: %s (%d chars)", query, |query|),
$conn=c]);
}
}
Splunk——来自 Zeek 的 DNS 隧道指标
index=zeek sourcetype=bro_dns
| rex field=query "(?<subdomain>[^.]+)\.(?<basedomain>[^.]+\.[^.]+)$"
| stats count dc(subdomain) as unique_subs avg(len(query)) as avg_len max(len(query)) as max_len by src basedomain
| where count > 100 AND (unique_subs > 50 OR avg_len > 40)
| sort -unique_subs
Splunk——高熵子域检测
index=zeek sourcetype=bro_dns
| rex field=query "^(?<subdomain>[^.]+)"
| where len(subdomain) > 20
| eval char_count=len(subdomain)
| stats count dc(query) as unique_queries avg(char_count) as avg_sub_len by src query_type_name basedomain
| where unique_queries > 30 AND avg_sub_len > 25
| sort -unique_queries
RITA 分析
rita import /path/to/zeek/logs dataset_name
rita show-dns-fqdn-ips-long dataset_name
rita show-exploded-dns dataset_name
rita show-dns-tunneling dataset_name --csv > dns_tunnel_results.csv
常见场景
- dnscat2 C2:将命令与控制流量编码在 DNS CNAME/TXT 查询中,使用 Base64 编码的子域标签。产生高查询量以及长而高熵的子域。
- iodine IPv4 隧道:创建一个虚拟网络接口,将所有 IP 流量通过 DNS 隧道传输。以 NULL 记录类型生成海量 DNS 查询量。
- 通过 DNS 进行数据外泄:将敏感数据编码在子域标签中(例如
aGVsbG8gd29ybGQ.exfil.attacker.com),以 A 或 TXT 查询发送。每个查询携带约 63 字节的数据。 - DNS-over-HTTPS 隧道:通过向公共解析器(8.8.8.8、1.1.1.1)发送基于 HTTPS 的 DNS 查询来绕过传统 DNS 监控,需要 TLS 检查才能检测。
- Cobalt Strike DNS Beacon:使用 DNS A/TXT 记录进行 C2 通信,具有可配置的子域编码方案。
输出格式
Hunt ID: TH-DNSTUNNEL-[DATE]-[SEQ]
Source IP: [Internal IP]
Source Host: [Hostname]
Target Domain: [Base domain]
Query Count: [Total queries in window]
Unique Subdomains: [Count]
Avg Query Length: [Characters]
Max Query Length: [Characters]
Subdomain Entropy: [Bits per character]
Primary Record Type: [A/TXT/CNAME/NULL]
Data Volume Estimate: [Bytes exfiltrated]
Risk Level: [Critical/High/Medium/Low]
评论
支持 Markdown