资产测绘实战:影子资产与攻击面发现配置

适用场景

资产测绘要解决的问题是:企业实际暴露在公网上的资产,往往多于自己登记在册的数量。早期做过的活动页、被遗忘的测试环境、第三方托管的表单系统、备案过却无人维护的域名,这些没有登记、又能从公网直接访问的资产就是影子资产,它们通常不受 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 这类零打扰数据源;二是必须做泛解析过滤,否则结果无法使用;三是把差集结果落到归属确认与整改动作上,否则测绘只会产出一张不断变长的清单。