适用场景
资产测绘要解决的问题是:企业实际暴露在公网上的资产,往往多于自己登记在册的数量。早期做过的活动页、被遗忘的测试环境、第三方托管的表单系统、备案过却无人维护的域名,这些没有登记、又能从公网直接访问的资产就是影子资产,它们通常不受 CDN 与 WAF 覆盖,是攻击者最喜欢的入口。
典型触发场景包括:等保测评或客户安全审计要求提交资产清单;发生入侵后复盘,发现攻击入口是一个没人记得的测试站;主站已接入 CDN/WAF,但某个子域名仍然直连源站 IP,绕过全部防护。
前置条件
- 一台可联网的 Linux 主机(Debian/Ubuntu 或 CentOS),具备正常外网 DNS 解析能力;
- 已获得目标域名与网段的书面授权。DNS 爆破与端口探测会触达目标,未经授权可能违反法律法规与云服务商条款;
- Go 1.21 以上或 Python 3.8 以上运行环境,用于安装测绘工具;
- 至少一个根域名;若有 CMDB、监控系统或工单系统的资产台账,可用于后续差集比对。
原理说明
公网侧资产发现可以归纳为六条路径:
- 证书透明度日志(CT Logs):CA 签发 SSL/TLS 证书时必须把证书提交到公开的 CT 日志,日志中沉淀了大量子域名记录。查询日志属于被动信息获取,不触碰目标;
- 被动 DNS 与公开数据集:历史解析记录、公开测绘平台数据;
- 主动 DNS 枚举:字典爆破子域名,必须处理泛解析(Wildcard)造成的海量误报;
- HTTP 存活与指纹识别:判断端口是否提供 Web 服务,并识别框架、CMS、云厂商与 CDN 特征;
- 端口与服务探测:发现非标准端口上的后台、数据库与中间件;
- 代码与配置泄露:前端 JS 中残留的内网域名、云存储桶地址、源码目录等。
判定影子资产的核心动作是差集运算:公网侧发现的资产集合,减去已在册(CMDB、监控、备案)的资产集合,剩余部分即为需要确认归属的影子资产。
操作步骤
1. 安装测绘工具链
ProjectDiscovery 系列工具覆盖了子域名枚举、DNS 解析、HTTP 探测与端口扫描四个环节:
go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest
go install -v github.com/projectdiscovery/dnsx/cmd/dnsx@latest
go install -v github.com/projectdiscovery/httpx/cmd/httpx@latest
go install -v github.com/projectdiscovery/naabu/v2/cmd/naabu@latest
export PATH=$PATH:$(go env GOPATH)/bin
无法安装 Go 时,可下载官方 release 的静态二进制直接运行,或用 Python 做基础校验:
pip3 install dnspython requests
2. 从 CT 日志被动枚举子域名
优先取被动数据,速度快且不触发目标侧告警:
curl -s "https://crt.sh/?q=%25.example.com&output=json" \
| python3 -c "import sys,json;[print(n) for e in json.load(sys.stdin) for n in e['name_value'].split('\n')]" \
| sed 's/\*\.//g' | sort -u > ct_subs.txt
wc -l ct_subs.txt
再用 subfinder 聚合多个被动源。参数 -all 表示启用全部数据源,-recursive 表示对发现的子域名继续递归枚举:
subfinder -d example.com -all -recursive -silent -o passive_subs.txt
cat ct_subs.txt passive_subs.txt | sort -u > subs.txt
wc -l subs.txt
3. 过滤泛解析,消除误报
很多域名配置了泛解析(*.example.com 一律解析到同一 IP),盲目爆破会得到成千上万条假结果。先用随机子域名探测基线 IP,再据此过滤:
RAND="zz$(date +%s)zz.example.com"
BASE_IP=$(dig +short "$RAND" | head -1)
echo "wildcard baseline: $BASE_IP"
if [ -n "$BASE_IP" ]; then
dnsx -l subs.txt -a -resp -silent \
| grep -v " $BASE_IP$" > resolved.txt
else
dnsx -l subs.txt -a -resp -silent > resolved.txt
fi
wc -l resolved.txt
4. HTTP 存活探测与指纹识别
httpx -l subs.txt -silent \
-status-code -title -tech-detect -web-server -cdn \
-follow-redirects -timeout 10 -threads 30 \
-o live.txt
column -t live.txt | head -30
结果重点看三类:状态码 200 且标题为默认页(例如 “Welcome to nginx!”),通常意味着存在未完成配置的暴露服务;401 或 403 说明后台入口对外开放;cdn=false 表示该域名直连源站,一旦被扫到就没有 WAF 遮挡,优先级最高。
5. 高危端口快速探测
naabu -l subs.txt -top-ports 1000 -rate 500 -silent -o ports.txt
grep -E ':(22|3306|5432|6379|8080|9200|27017)$' ports.txt
对命中的 IP 用 nmap 做服务版本确认,避免仅凭端口号下结论:
nmap -sV -Pn -p 6379 --script redis-info 1.2.3.4
6. 与在册清单比对,输出影子资产
cut -d' ' -f1 live.txt | cut -d: -f1 | sort -u > found_hosts.txt
sort -u assets_cmdb.txt > known_hosts.txt
comm -23 found_hosts.txt known_hosts.txt > shadow_assets.txt
echo "影子资产数量: $(wc -l < shadow_assets.txt)"
cat shadow_assets.txt
对每一条影子资产,需要确认三件事:归属部门与业务方、是否仍在对外提供服务、能否下线或收编到统一的 CDN/WAF 之后。无法确认归属且无业务用途的,应直接停服或删除对应 DNS 记录。
7. 固化为周期性任务
cat > /etc/systemd/system/asm-scan.service <<'EOF'
[Unit]
Description=Attack Surface Discovery
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/asm-scan.sh
EOF
cat > /etc/systemd/system/asm-scan.timer <<'EOF'
[Unit]
Description=Daily attack surface scan
[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true
[Install]
WantedBy=timers.target
EOF
systemctl daemon-reload && systemctl enable --now asm-scan.timer
配置验证
- 枚举完整性:用已知存在的子域名(如 www、mail、api)反向校验,确认它们出现在结果文件中。若缺失,说明数据源覆盖不足,应补充被动 DNS 源或扩大字典;
- 误报率:随机抽取 20 条影子资产人工确认,误报率应低于 10%。泛解析未过滤时误报率会接近 100%;
- 扫描强度:观察目标侧是否出现 WAF 拦截告警,把 -threads 与 -rate 下调到不触发风控的水平;
- 结果可解释:连续两天运行,新增资产应当能解释来源(新上线、新签发证书)。若出现大量随机波动,需检查泛解析过滤是否失效。
常见问题
FAQ 1:为什么证书透明度日志能枚举出子域名?
主流 CA 在签发 SSL/TLS 证书时,按规范必须把证书提交到公开的 CT 日志,任何人都能查询。只要某个子域名签发过公网证书,哪怕只是内网系统临时用免费证书签过,域名就会长期留存在日志中。这也是内部系统不应直接申请公网证书的原因之一:一旦签过,域名就等于公开了。若必须使用,应改用内部 CA 签发。
FAQ 2:泛解析导致结果里全是假子域名,怎么处理?
先探测随机前缀的解析结果作为基线 IP,再把解析到该 IP 的全部子域名剔除(见步骤 3)。更稳妥的做法是叠加 HTTP 指纹二次过滤:泛解析通常返回同一张默认页,可用页面内容哈希或 -title 结果去重。若目标同时使用 CDN,基线 IP 可能随节点变化,需要多次采样取并集。
FAQ 3:主动扫描会不会被当成攻击行为?
存在这个风险。正确的顺序是「先被动、后主动」:查 CT 日志与被动 DNS 属于读取公开数据,不会触达目标;DNS 爆破与端口扫描会命中目标日志与 WAF。务必在授权范围内操作,控制速率(naabu 的 -rate 建议不超过 500),并提前与运维或安全团队报备时间窗口,避免触发应急响应流程。
总结
资产测绘的价值不在于扫出多少子域名,而在于让「公网可见资产」与「在册资产」保持一致。落地时把握三个要点:一是优先使用 CT 日志与被动 DNS 这类零打扰数据源;二是必须做泛解析过滤,否则结果无法使用;三是把差集结果落到归属确认与整改动作上,否则测绘只会产出一张不断变长的清单。