第三章:资产发现与清单管理
说实话,做供应链安全这几年,我见过太多团队栽在同一个坑里——连自己有什么资产都没搞清楚,就开始搞漏洞排查。这就像你连家里有多少扇窗户都不知道,就急着要装防盗网,你说荒唐不荒唐?
我个人习惯,做任何安全项目之前,第一件事就是摸清家底。今天我们就聊聊,怎么自动发现供应链里的那些资产,以及怎么维护这份清单。
3.1 资产发现:你到底有哪些家底?
供应链里的资产,说白了就四类:IP、域名、代码仓库、第三方组件。每一类都有它自己的脾气,得用不同的法子去发现。
3.1.1 IP 资产发现
IP 这东西,最容易被忽略。很多公司只记得自己的公网 IP,内网段、云上 VPC 里的 IP 全忘了。我在项目中遇到过一家公司,他们以为自己只有 10 个公网 IP,结果我一扫,发现还有 30 多个没人管的 IP 挂在云上,其中一台还跑着旧版本的 OpenSSH。
常用的自动发现手段:
- DNS 解析记录:从你的 DNS 服务器里导出所有 A 记录和 CNAME 记录
- CDN 日志:从 CDN 日志里提取源站 IP
- 云服务商 API:调用 AWS/GCP/Azure 的 API,拉取所有实例的 IP
- 网络扫描:用 Nmap 或 Masscan 扫描已知网段
3.1.2 域名资产发现
域名比 IP 更麻烦。为什么?因为域名可以无限嵌套子域名。你想想看,一个主域名下面可能挂着几百个子域名,有些子域名甚至没人记得是谁创建的。
我记得有一次帮客户做排查,他们只提供了 5 个主域名。我用工具一跑,发现关联了 200 多个子域名,其中有个子域名指向一个测试环境,上面跑着生产数据库的备份。嗯,这种事儿真不少见。
自动发现域名的常用方法:
- 证书透明度日志:从 crt.sh 拉取所有关联域名
- 搜索引擎:用 Google/Bing 的 site: 语法
- DNS 枚举:用 dnsrecon 或 subfinder 暴力枚举子域名
- 被动 DNS:从 SecurityTrails 等平台获取历史 DNS 记录
# 一个简单的子域名发现脚本示例
#!/bin/bash
DOMAIN="example.com"
# 从 crt.sh 拉取证书日志
curl -s "https://crt.sh/?q=%25.$DOMAIN&output=json" | \
jq -r '.[].name_value' | \
sort -u > subdomains.txt
echo "发现 $(wc -l < subdomains.txt) 个子域名"
3.1.3 代码仓库发现
代码仓库这块,水更深。大公司可能有几百个 Git 仓库,有些是公开的,有些是私有的,还有些是员工自己建的。我曾经见过一个案例,某员工把自己的 GitHub 仓库设成了公开,里面居然写着数据库连接密码。
自动发现代码仓库的方法:
- GitHub/GitLab API:通过组织名拉取所有仓库列表
- 代码扫描工具:用 GitLeaks 或 TruffleHog 扫描公开仓库
- CI/CD 日志:从 Jenkins/GitLab CI 日志里提取仓库地址
- 依赖文件分析:从 package.json、requirements.txt 里反向推断仓库
3.1.4 第三方组件发现
第三方组件,说白了就是那些你从外面拿来的代码。npm 包、Maven 依赖、PyPI 包、Docker 镜像……这些东西你用得爽,但风险也最大。一个 Log4j 事件,全球多少公司中招?
自动发现第三方组件的方法:
| 组件类型 | 发现方法 | 常用工具 |
|---|---|---|
| JavaScript 包 | 解析 package-lock.json | npm audit, Snyk |
| Java 包 | 解析 pom.xml 或 build.gradle | OWASP Dependency-Check |
| Python 包 | 解析 requirements.txt 或 Pipfile.lock | pip-audit, Safety |
| Docker 镜像 | 扫描 Dockerfile 或镜像层 | Trivy, Clair |
| Go 模块 | 解析 go.mod 和 go.sum | govulncheck |
3.2 资产清单维护:别让清单变成废纸
发现资产只是第一步。更难的是怎么维护这份清单。我见过太多团队,花了两周时间整理出一份资产清单,然后就扔在共享文件夹里吃灰。三个月后,清单上的信息已经过时了,还不如没有。
为什么会这样?因为资产是动态的。新服务上线、旧服务下线、IP 变更、域名新增……每天都在变。你想想看,如果清单不跟着变,那它还有什么用?
3.2.1 自动化更新策略
我个人建议,资产清单的更新必须自动化。手动更新?不存在的。人都会偷懒,都会忘记。
- 定时扫描:每天凌晨跑一次资产发现脚本,自动比对差异
- 事件驱动:监听云服务商的 EventBridge 或 Webhook,有新资源创建时自动更新
- CI/CD 集成:在流水线里加入资产注册步骤,每次部署自动更新清单
# 一个简单的资产差异比对脚本
#!/bin/bash
# 获取当前资产列表
curl -s "https://api.example.com/assets" | jq '.' > current_assets.json
# 与上次的清单比对
diff -q current_assets.json last_assets.json
if [ $? -ne 0 ]; then
echo "资产清单有变化!"
# 发送通知
curl -X POST "https://hooks.slack.com/..." \
-d '{"text":"资产清单已更新"}'
# 保存当前清单
cp current_assets.json last_assets.json
fi
3.2.2 资产生命周期管理
资产不是永生的。它也有生命周期:创建、运行、下线、销毁。很多公司只关注前两个阶段,忽略了后两个。结果就是,一堆已经下线的资产还挂在清单上,浪费存储空间不说,还容易误导人。
我建议给每个资产打上状态标签:
- active:正常运行中
- deprecated:已废弃,但还未下线
- decommissioned:已下线,保留记录
- unknown:状态不明,需要人工确认
3.2.3 资产归属与责任人
每项资产都必须有明确的责任人。没有责任人的资产,就是没人管的孤儿。我曾经处理过一个事故,一个内部 API 被攻击了,结果查了半天,没人知道这个 API 是谁部署的。最后发现是某个离职员工三年前做的实验项目。
所以,资产清单里必须包含:
- 负责人:当前谁在维护
- 创建人:谁创建的
- 业务线:属于哪个部门
- 联系方式:紧急联系人
- 最后更新时间:上次确认的时间
3.3 避坑指南
做了这么多年供应链安全,我踩过的坑不少。分享几个典型的:
还有一个坑:别太相信自动发现工具。工具只能发现它知道的东西。有些资产,比如内部自建的代码仓库、老旧的 FTP 服务器,工具可能扫不到。所以,自动发现 + 人工确认,才是王道。
嗯,最后说一句:资产清单不是做给别人看的,是给你自己用的。别为了应付审计而做清单,要为了真正管理风险而做。这个心态不摆正,后面所有的工作都是白搭。