关于 hunt-tls-network
用于在授权目标上检查 TLS、DNS、邮件认证、响应头及相关暴露面的安全测试技能。它强调验证实际影响和项目范围,而非仅报告配置缺失。
主要功能
- 01审计 TLS 和 SSL 配置
- 02检查 HSTS 和安全响应头
- 03测试 DNS 区域传送
- 04评估 SPF、DKIM 和 DMARC
- 05从证书日志发现子域名
- 06验证悬空记录和 mTLS 绕过
适用场景
- 01评估范围内主机的 TLS 风险
- 02确认邮件仿冒是否进入收件箱
- 03发现暴露的 DNS 记录或子域名
- 04验证疑似子域名接管
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ uphiago/ recon-skills --skill hunt-tls-network安装后在 Claude Code 中输入/hunt-tls-network确认已加载。
详细介绍
HUNT-TLS-NETWORK — TLS/SSL 与 DNS 安全
现实情况核查(请先阅读)
此类发现大多属于信息级/低危,且经常在分诊时被以「最佳实践」/「缺少加固」为由拒绝。编写此技能是为了避免你浪费时间提交报告。在报告此类问题之前,请先问自己两个问题:
- 是否存在真实受害者和真实操作?「缺少 HSTS」不是漏洞——从你实施中间人攻击的受害者那里实际捕获会话 Cookie 才是。「缺少 CAA」永远不是你能证明的漏洞。
- 该计划是否接受此类问题?许多计划明确将缺少 SPF/DMARC、安全标头、没有可利用漏洞的弱加密套件,以及 CAA 列为不在范围内。先阅读范围说明;在报告中引用范围内的条款。
此类问题中真正有价值的发现(按优先级排序):
- 悬空 CNAME/悬空 A 记录导致的子域名接管——你能控制
target.com子域名上的内容。影响真实,确有赏金。(由hunt-subdomain负责深入检测;此处从 TLS/DNS 侦察角度介绍。) - 可被伪造的 DMARC,且有邮件送达收件箱的证明——不是「存在 p=none」,而是实际发送一封来自
[email protected]的邮件,并成功送达真实收件箱,且邮件头中的 DMARC 判定为通过/none。 - DNS AXFR 返回内部主机——获得完整的内部主机名/IP 映射。具有明确的侦察价值,通常为中危。
- 内部服务上的 mTLS/客户端证书绕过——无需证书即可访问仅限认证用户使用的功能。真实的认证绕过=高危。
- 可通过有效解密/中间人攻击 PoC 利用的 TLS 弱点——在 2024-2026 年,针对已修补的协议栈,几乎不可能远程实现;请参阅阶段 1 的注意事项。
**没有价值的发现(不要单独报告):**缺少 CAA;没有 MitM PoC 的情况下缺少 HSTS;单独缺少安全标头;不带利用方式的弱加密套件支持;非生产环境主机上的自签名证书;启用了 TLS 1.0/1.1,但没有降级攻击受害者。
阶段 1 — TLS/SSL 审计
# Quick TLS test with testssl.sh
brew install testssl
testssl.sh --fast $TARGET 2>/dev/null | grep -E "CRITICAL|HIGH|MEDIUM|OK|NOT" | head -30
# Or use sslyze (Python)
pip3 install sslyze
python3 -m sslyze $TARGET --json_out /tmp/sslyze_$TARGET.json 2>/dev/null
cat /tmp/sslyze_$TARGET.json | python3 -m json.tool | grep -i "vulnerability\|insecure\|error" | head -20
# Check certificate expiry and chain
echo | openssl s_client -connect $TARGET:443 -servername $TARGET 2>/dev/null | \
openssl x509 -noout -dates -subject -issuer 2>/dev/null
# Check for weak ciphers manually (a successful handshake = the cipher is OFFERED, not exploitable)
openssl s_client -connect $TARGET:443 -cipher RC4-SHA 2>/dev/null | grep -i "cipher\|handshake"
openssl s_client -connect $TARGET:443 -cipher DES-CBC3-SHA 2>/dev/null | grep -i "cipher\|handshake"
# Protocol downgrade surface — TLS 1.0/1.1 still negotiable?
openssl s_client -connect $TARGET:443 -tls1 2>/dev/null | grep -E "Protocol|Cipher"
openssl s_client -connect $TARGET:443 -tls1_1 2>/dev/null | grep -E "Protocol|Cipher"
准确性/分诊注意事项——不要夸大 TLS 漏洞:
- **支持 ≠ 可利用。**testssl/sslyze 标记出 RC4、3DES 或 TLS 1.0,意味着服务器可以协商使用这些协议或算法。这属于加固问题,并不代表已证明可以解密。没有 PoC 时,该问题为信息级/低危,且经常不在范围内。
- SWEET32(CVE-2016-2183)——3DES 生日攻击。需要持续时间很长的 TLS 会话、处于链路上的攻击者,以及约数百 GB/数小时的同密钥流量。在漏洞赏金计划中,实际上无法证明;只能报告对 3DES 的支持,并预期评级为低危/信息级。
- POODLE(CVE-2014-3566)——SSLv3 CBC 填充预言机攻击。需要实际启用 SSLv3;几乎没有现代协议栈会提供此协议。请使用
testssl.sh --poodle(或nmap --script ssl-poodle)确认——现代版 OpenSSL 3.x 已移除-ssl3标志。如果无法协商 SSLv3,就不存在 POODLE。 - FREAK(CVE-2015-0204)和DROWN(CVE-2016-0800)——分别需要出口级 RSA 和共享 SSLv2 端点。两者都必须证明条件确实存在,不能想当然。DROWN 要求某个共享证书/密钥的主机可以访问 SSLv2——在声称存在此问题之前,请对证书的 SAN 列表中的所有主机使用
testssl.sh --drown(或nmap --script sslv2-drown)扫描 SSLv2;现代版 OpenSSL 没有-ssl2标志。 - Heartbleed(CVE-2014-0160)——如果你确实发现了一个未修补、会泄露内存的 OpenSSL 1.0.1,那么只要有真实 PoC(泄露的数据中包含密钥/Cookie),该问题确实属于高危/严重。请使用
testssl.sh --heartbleed验证并捕获泄露的字节;这是少数值得提交完整报告的 TLS 漏洞。
阶段 2 — HSTS 检查
# Check HSTS header on main domain and all subdomains
curl --max-time 30 --connect-timeout 10 -sI "https://$TARGET/" | grep -i "strict-transport-security"
# Expected: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
# Check critical subdomains (login, api, auth)
for sub in login auth api account pay www; do
HSTS=$(curl --max-time 30 --connect-timeout 10 -sI "https://$sub.$TARGET/" 2>/dev/null | grep -i "strict-transport-security")
if [ -z "$HSTS" ]; then
echo "[!] MISSING HSTS: https://$sub.$TARGET/"
else
echo "[OK] $sub.$TARGET: $HSTS"
fi
done
# Check HTTP (non-HTTPS) redirect
curl --max-time 30 --connect-timeout 10 -sI "http://$TARGET/" | grep -i "location"
# Should redirect to HTTPS immediately
# HSTS preload check
curl --max-time 30 --connect-timeout 10 -s "https://hstspreload.org/api/v2/status?domain=$TARGET" | python3 -m json.tool 2>/dev/null
阶段 3 — DNS 区域传送(AXFR)
# Find nameservers
dig NS $TARGET +short
# Attempt zone transfer on each nameserver
for NS in $(dig NS $TARGET +short); do
echo "=== Trying AXFR from $NS ==="
dig AXFR $TARGET @$NS 2>/dev/null | grep -v "^;" | head -30
done
# Zone transfer via alternativetools
host -t AXFR $TARGET $(dig NS $TARGET +short | head -1) 2>/dev/null | head -30
nmap -sn --script dns-zone-transfer $TARGET 2>/dev/null | head -30
# If AXFR succeeds → full internal hostname map
# Look for: internal IPs, staging servers, admin hostnames, CI/CD servers
阶段 4 — 邮件安全(SPF/DKIM/DMARC)
# Check SPF record
dig TXT $TARGET +short | grep "v=spf1"
# Missing SPF → potential email spoofing
# Check DMARC
dig TXT _dmarc.$TARGET +short
# Missing DMARC → attacker can send as @target.com with no enforcement
# Check DKIM selectors (common: default, google, mail, k1)
for selector in default google mail k1 selector1 selector2 s1 s2 dkim; do
RESULT=$(dig TXT $selector._domainkey.$TARGET +short 2>/dev/null)
[ -n "$RESULT" ] && echo "DKIM selector found: $selector → $RESULT"
done
# --- Spoofability evaluation (heuristic only; PROOF is the swaks test below) ---
SPF=$(dig +short # Bulk: dnsx -silent -l file -a -resp-only TXT $TARGET | tr -d '"' | grep -i "v=spf1")
DMARC=$(dig +short # Bulk: dnsx -silent -l file -a -resp-only TXT _dmarc.$TARGET | tr -d '"' | grep -i "v=DMARC1")
# SPF "+all" / "all" with no qualifier = pass-everything = spoofable from any IP
echo "$SPF" | grep -Eq '[+ ]all($|[^-~?])' && echo "[CRITICAL] SPF passes all senders (+all)"
echo "$SPF" | grep -q "~all" && echo "[INFO] SPF softfail (~all) — may still deliver to inbox"
[ -z "$SPF" ] && echo "[INFO] No SPF record"
# Correct DMARC-absence check: test the variable for emptiness, do NOT pipe dig|wc -c
if [ -z "$DMARC" ]; then
echo "[INFO] No DMARC record (no published policy)"
else
POLICY=$(echo "$DMARC" | grep -oiE 'p=[a-z]+' | head -1)
echo "[INFO] DMARC present: $POLICY"
echo "$POLICY" | grep -qi "p=none" && echo " -> p=none: monitors only, does NOT block spoofed mail"
echo "$POLICY" | grep -qiE "p=(quarantine|reject)" && echo " -> enforcing policy: spoofing likely blocked at receiver"
fi
为什么原先的 dig ... | wc -c | grep '^1$' 检查存在问题:dig +short # Bulk: dnsx -silent -l file -a -resp-only 的输出为空时,结果是长度为零的字符串;通过管道传给 wc -c 后通常会得到 0,而换行符的处理方式因 Shell 而异,因此 ^1$ 匹配会在两种情况下都出错。请始终将结果赋给变量,并使用 [ -z "$VAR" ] 进行判断。
可伪造性由接收方决定,不是靠读取记录来判断
不要只凭 dig 输出就报告“缺少 DMARC = 电子邮件可被伪造”。DMARC p=none(或不存在)意味着发送域未发布强制策略——但接收方邮件服务商(Gmail、M365、目标程序自己的 MX)仍可能根据 SPF、自身启发式规则或 ARC,将你的伪造邮件送入垃圾邮件文件夹或拒收。只有成功投递到真实收件箱的邮件,才是经得起分诊审查的证据。
# PROOF: send a spoofed mail and confirm INBOX delivery (use a tester account you own)
# Use an account on the receiver the program actually uses (check their MX: dig MX $TARGET)
swaks --to [email protected] \
--from "CEO <ceo@$TARGET>" \
--header "Subject: [TEST] DMARC spoof PoC for $TARGET" \
--body "Authorized bug-bounty test. Spoofed from-domain: $TARGET" \
--server <an-smtp-relay-you-control-or-localhost>
确认门槛——只有满足以下条件,伪造 PoC 才有效:
- 邮件进入了收件箱(不是垃圾邮件/Spam),并截取文件夹的屏幕截图。
- 原始标头中:
Authentication-Results:显示dmarc=none|fail,且邮件仍然成功投递(未退信)。退信或进入垃圾邮件文件夹都不算漏洞发现——记下结果后继续。 - 收件人看到的
From:显示@$TARGET(标头 From 伪造,这是钓鱼攻击真正关心的部分),而不只是耍envelope-from花招。
严重性最高为中危,且仅在邮件成功投递到收件箱时成立。许多计划会直接将电子邮件身份验证问题标记为超出范围(OOS)——先检查范围。
阶段 5 — 安全标头审计
# Check all security headers
HEADERS=$(curl --max-time 30 --connect-timeout 10 -sI "https://$TARGET/")
# Check each critical header
for HEADER in "Strict-Transport-Security" "Content-Security-Policy" "X-Frame-Options" \
"X-Content-Type-Options" "Referrer-Policy" "Permissions-Policy"; do
RESULT=$(echo "$HEADERS" | grep -i "$HEADER")
if [ -z "$RESULT" ]; then
echo "[MISSING] $HEADER"
else
echo "[OK] $HEADER: $RESULT"
fi
done
# Automated security headers check
curl --max-time 30 --connect-timeout 10 -s "https://securityheaders.com/?q=https://$TARGET&followRedirects=on" | \
grep -Eo "grade-\K[A-F+]" | head -3
阶段 6 — 证书透明度(子域名发现)
# crt.sh — certificate transparency logs
curl --max-time 30 --connect-timeout 10 -s "https://crt.sh/?q=%25.$TARGET&output=json" | \
python3 -m json.tool 2>/dev/null | grep "name_value" | \
grep -Eo '"name_value": "\K[^"]+' | \
sed 's/\*\.//g' | sort -u > recon/$TARGET/ct-subdomains.txt
echo "[+] CT subdomains found: $(wc -l < recon/$TARGET/ct-subdomains.txt)"
# Compare with existing subdomain list
comm -23 <(sort recon/$TARGET/ct-subdomains.txt) \
<(sort recon/$TARGET/subdomains.txt 2>/dev/null) | head -20
# New entries = recently issued certs = new services to investigate
阶段 6.5 — 悬空记录 → 子域名接管(真正有价值的发现)
这是整个技能中影响最大的项目。指向已停用第三方资源(S3 存储桶、Azure CDN/App Service、GitHub Pages、Heroku、Fastly 等)的 CNAME/A 记录,可让你认领该资源,并从 *.target.com 提供内容。完整内容请参阅 hunt-subdomain;以下是 TLS/DNS 侦察的入门内容。
# For each subdomain from CT logs, resolve the CNAME chain and check for a live origin
while read sub; do
CNAME=$(dig +short # Bulk: dnsx -silent -l file -a -resp-only CNAME "$sub" | head -1)
[ -z "$CNAME" ] && continue
CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 8 --connect-timeout 8 "https://$sub/" 2>/dev/null)
echo "$sub -> $CNAME [http $CODE]"
done < recon/$TARGET/ct-subdomains.txt | tee recon/$TARGET/cname-map.txt
# Flag CNAMEs that point at known takeoverable providers, then confirm the
# fingerprint string in the body (e.g. "NoSuchBucket", "There isn't a GitHub Pages site here",
# "Fastly error: unknown domain", "The specified bucket does not exist", Azure "Web App - Unavailable").
验证门槛——要声称存在接管漏洞,你必须实际完成认领:
- 确认悬空目标未注册/可认领(S3 存储桶名称可用、Heroku 应用不存在等)——仅凭服务商错误特征虽然必要,但远远不够。
- 自行注册该资源并提供唯一的金丝雀文件,例如让
https://$sub/<random>.txt返回只有你知道的字符串。截取通过受害者子域名和有效 TLS 提供该文件的屏幕截图。 - PoC 完成后立即拆除资源;绝不要让攻击者控制的内容继续留在目标域名上。
影响:窃取 Cookie 作用域(为 .target.com 设置的 Cookie)、滥用 OAuth redirect_uri/CORS 信任、在受信任的源上进行钓鱼。通常为高危(如果位于 OAuth/SSO 重定向处或共享会话 Cookie,则为严重)。
阶段 7 — CAA 记录(仅作侦察信号,不是可报告的发现)
# CAA records DECLARE which CAs the domain owner permits to issue certs.
dig CAA $TARGET +short
dig CAA "*.$TARGET" +short
**不要将“缺少 CAA”报告为漏洞。**这是此类问题中最常见的误报。正确的表述如下:
- **缺少 CAA 记录不会让攻击者获得证书。**这只意味着所有者尚未选择限制哪些 CA 可以签发证书。无论是否配置 CAA,攻击者仍需通过域名控制权验证(HTTP-01 / DNS-01 / 电子邮件验证)——这要求攻击者已经控制该域名、DNS 或 Web 根目录。
- “欺诈性签发”情形需要CA 被攻破,或通过社会工程诱使 CA 错误签发证书。这几乎始终超出漏洞赏金计划的范围,也无法通过实际操作证明。CAA 强制执行是 CA 端的控制措施,不是面向攻击者的攻击面。
- CAA 最多只能算信息级加固建议,而且通常会以 Won't-Fix / OOS 结案。若要提及,可放在侦察笔记附录中;绝不要单独提交报告。
CAA 侦察的实用价值(不构成漏洞发现,仅供参考):issue/issuewild 值可以告诉你组织使用哪家 CA(例如 letsencrypt.org、digicert.com、amazon.com)。这能暗示其是否使用自动化(ACME),也能提示在何处发生的真实接管(阶段 6.5 的悬空记录)可能让你通过 DCV 签发有效证书,因为你将控制该主机。
阶段 8 — mTLS 绕过尝试
# Check if endpoint requires client certificate
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/internal/" 2>&1 | grep -i "ssl\|certificate\|403\|401"
# Try without client cert (should fail)
curl --max-time 30 --connect-timeout 10 -sk --cert "" "https://$TARGET/internal/api" | head -5
# Try common bypass paths (some apps skip mTLS on health checks)
for path in /health /ping /status /metrics /api/health; do
STATUS=$(curl --max-time 30 --connect-timeout 10 -sk -o /dev/null -w "%{http_code}" "https://$TARGET$path")
echo "$path: $STATUS"
done
# Header-injection bypass — nginx/HAProxy/Envoy commonly terminate mTLS at the edge and
# forward the verdict as a request header the backend trusts. If the edge does NOT strip
# client-supplied copies of that header, you spoof a verified client. Try the real header
# names used by each proxy:
for combo in \
"X-SSL-Client-Verify: SUCCESS|X-SSL-Client-S-DN: CN=admin" \
"ssl-client-verify: SUCCESS|ssl-client-subject-dn: CN=admin" \
"X-Client-Verify: SUCCESS|X-Client-DN: CN=admin,O=target" \
"X-Forwarded-Client-Cert: By=spiffe://x;Hash=0;Subject=\"CN=admin\""; do
H1="${combo%%|*}"; H2="${combo##*|}"
echo "== $H1 / $H2 =="
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/internal/api" -H "$H1" -H "$H2" -o /dev/null -w "%{http_code}\n"
done
mTLS 绕过验证——这是真正的身份验证绕过,因此要证明能够访问,而不只是提供状态码:
200可能只是通用页面。请确认已访问仅限已验证用户使用的功能:展示没有客户端证书就无法获取的数据或执行的操作(例如仅限管理员访问的对象、仅限内部访问的响应正文)。- 区分服务器策略与服务器状态:如果伪造请求头后状态码从
403变为200,这有意义;如果有无该请求头都是200,则说明该路径从未受保护(不构成发现)。 - 对于绕过路径(
/health、/metrics),只有端点暴露了敏感数据(内部 IP、构建密钥、泄露内部拓扑的 Prometheus 指标)时,才构成发现——返回空200 OK的健康探测不算。 - 在 Burp Repeater 中捕获请求/响应对,清晰证明伪造请求头 → 特权响应。
漏洞链汇总表
下列严重性等级依据实际分诊接受的标准校准,刻意保持保守;请勿在报告中夸大。
| TLS/DNS 发现 | 现实中单独报告的严重性 | 备注 / 提升严重性的因素 |
|---|---|---|
| 悬空 CNAME 子域名接管(已认领并提供金丝雀内容) | 高 | 若用于 OAuth redirect_uri/SSO,或共享 .target.com 会话 Cookie,则为严重 |
| mTLS / 客户端证书绕过并访问已验证用户功能 | 高 | 必须展示特权数据/操作,而不只是 200 |
| AXFR 返回内部主机/IP | 中 | 具有侦察价值;可与内部服务发现结合 |
| 可伪造 DMARC,且已送达真实收件箱(PoC 邮件头) | 中 | 通常超出范围(OOS)——请检查范围;必须送达收件箱(而非垃圾邮件)。仅通过 dig 读取 p=none = 信息级,不要提交 |
| Heartbleed / 实时内存泄漏并捕获到密钥 | 高–严重 | 仅限实际转储中包含密钥/ Cookie 的情况 |
| 身份验证子域缺少 HSTS | 低 / 信息级 | 不是高危——利用需要主动 MitM 位置,无法远程证明;仅在有可行的降级捕获 PoC 时报告 |
| 支持弱密码套件(RC4/3DES/SWEET32)但没有解密 PoC | 信息级 / 低 | 仅涉及安全加固;经常超出范围(OOS) |
| 缺少 CAA | 信息级(不要提交) | 缺失并不允许签发证书;无法由攻击者证明 |
工具
# testssl.sh — comprehensive TLS audit
brew install testssl
testssl.sh $TARGET
# sslyze — Python TLS scanner
pip3 install sslyze
# MXToolbox for email security
curl --max-time 30 --connect-timeout 10 -s "https://mxtoolbox.com/api/v1/Lookup/spf?argument=$TARGET" 2>/dev/null
# dmarc-inspector
curl --max-time 30 --connect-timeout 10 -s "https://dmarcian.com/dmarc-inspector/?domain=$TARGET" 2>/dev/null
验证
每项发现都必须附带所列证明——绝不能只提供 dig/请求头输出。
- **子域名接管:**你已注册悬空资源,并通过
https://sub.target.com/使用有效 TLS 提供唯一的金丝雀内容。附上截图和金丝雀字符串。(之后撤除。) - **mTLS 绕过:**伪造客户端验证请求头后,返回特权数据/操作,而证书必需的路径会拒绝该请求。附上 Burp 请求/响应对。
- **AXFR:**区域传送从权威 NS 返回内部主机名/IP。附上完整记录。
- DMARC 欺骗:使用 swaks 发送
From: @target.com邮件,且已送达真实收件箱(而非垃圾邮件),并附上原始Authentication-Results请求头。退信或进入垃圾邮件均不构成发现。 - **缺少 HSTS:**只有在有可行的降级 PoC 并捕获到受害者通过明文传输的 Cookie 时,才可报告;否则只是最佳实践层面的噪声。
严重性(保守标准——与漏洞链汇总表一致):
- 子域名接管(已认领):高(用于 OAuth/SSO 重定向或共享会话 Cookie 时为严重)
- 绕过 mTLS 并访问已验证用户功能:高
- AXFR 返回内部主机:中
- DMARC 欺骗并送达收件箱:中(通常超出范围(OOS)——请核实范围)
- 身份验证页面缺少 HSTS(有降级 PoC):低–中;无 PoC:信息级
- 支持弱密码套件但无解密 PoC:信息级–低
- 仅缺少安全请求头 / 缺少 CAA:信息级(通常不要提交)
**提交前范围检查:**提交此处的任何项目之前,请确认项目未将其列为超出范围(邮件身份验证、缺少请求头、无漏洞利用的弱 TLS,以及 CAA 通常都超出范围(OOS))。请在报告中引用范围内条款。
验证
运行此自测,确认已准备好进行 tls-network 排查:
-
技能完整性 — 确认技能文件可读且格式正确:
grep -q "name: hunt-tls-network" SKILL.md && echo "PASS: skill frontmatter present" || echo "FAIL" grep -q "revision_date:" SKILL.md && echo "PASS: revision date present" || echo "FAIL" -
类别检查 — 确认技能已设置类别:
grep -q "category:" SKILL.md && echo "PASS: category present" || echo "FAIL" -
陷阱部分 — 确认已记录相关陷阱:
grep -q "^## Pitfalls" SKILL.md && echo "PASS: pitfalls section present" || echo "FAIL"
这 3 项测试可验证技能结构正确且已准备就绪。
陷阱
- TLS 版本但无漏洞利用 — 支持 TLS 1.0/1.1 属于配置问题,而非漏洞(除非同时存在特定的降级攻击)。
- 弱密码套件但无漏洞利用 — RC4、3DES 等密码套件较弱,但要利用它们需要主动中间人攻击。请记录攻击场景。
- 自签名证书 — 自签名证书在内部服务中很常见。在公共服务中,这会带来钓鱼风险(低至中)。
- 证书透明度日志监控 — 通过 CT 日志查找子域名属于侦察,而非漏洞。真正的问题在于这些子域名暴露了什么。
- Heartbleed/POODLE 测试 — 这些旧版 TLS 漏洞在 2024 年及以后极为罕见。请进行测试,但不要投入过多时间。