ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SBOM漏洞扫描实操:用CVE Binary Tool快速匹配CVE并生成报告

SBOM漏洞扫描实操:用CVE Binary Tool快速匹配CVE并生成报告 你手里有没有这样一份文件里面一行行列着你项目里所有第三方组件的名称、版本、依赖关系客户或甲方拿到手第一句话就是漏洞情况呢SBOM 这个词这两年已经成了软件供应链交付的硬通货但很多人把生成 SBOM 当成终点交完文件就以为万事大吉。实际上SBOM 真正有价值的用途是拿它去做漏洞匹配把自己的组件清单跟公开漏洞库对照一遍找出哪些版本命中已知 CVE。这时候 CVE Binary Tool 就派上用场了它能直接吃下 SBOM 文件把里面每个组件的已知漏洞全部拉出来生成一份可交付的漏洞报告。这篇文章就是围绕“用 CVE Binary Tool 扫描 SBOM”这个场景做的完整实操记录。我假设你已经有一个 SBOM 文件可能是 CycloneDX 格式也可能是 SPDX 格式也可能你还没有 SBOM需要现场生成一份。我会把工具安装、SBOM 格式说明、核心扫描命令、报告解读、常见坑点全部过一遍。适合三类人看一是做交付需要补漏洞报告的同学二是在 CI 流水线里加安全检查的运维或开发三是想搞懂 SBOM 后续能干什么的初学者。1. 为什么要拿 CVE Binary Tool 扫 SBOM1.1 SBOM 是软件的“配料表”扫描要找准输入SBOM 全称 Software Bill of Materials软件物料清单。你可以把它理解成食品包装上的配料表一份正式的 SBOM 里会列出软件中包含哪些第三方库、每个库的版本、许可证、依赖层级甚至打包产物的哈希值。不同公司的 SBOM 长得不一样但主流格式基本收敛到两类CycloneDX 和 SPDX。前者由 OWASP 社区推动结构偏漏洞管理和依赖分析后者是 Linux 基金会主导更侧重许可证合规。你拿到手的不管是哪种核心都是在回答一个问题这个软件里到底装了什么、是什么版本。过去没有 SBOM 的时候团队想知道自己用了哪些组件一般靠两种土办法翻 package-lock.json、requirements.txt 之类的依赖锁定文件或者直接在构建产物目录里搜字符串特征。这两种方式都有明显的问题。锁定文件只能覆盖构建环节的依赖运行时动态加载的、手工拷贝进目录的、被某个安装脚本带进来的组件统统看不见搜字符串特征又太粗同名库不同版本匹配不上很容易误报。SBOM 把这份清单标准化、结构化扫描工具就不需要自己去猜目录里有什么了直接解析文件就行。但这里容易产生一个误区SBOM 本身不包含漏洞信息它只是组件清单相当于告诉你“我用了 OpenSSL 1.1.1k”但不会告诉你这个版本有哪些 CVE。要把清单变成风险报告必须把组件版本拿去跟漏洞库比对。市面上能做这件事的工具不少Trivy、Grype、OWASP Dependency-Check 都支持 SBOM 输入CVE Binary Tool 也是其中一个而且它的优势很明确轻量、开源、专为二进制与 SBOM 场景设计。1.2 CVE Binary Tool 为什么适合这个场景CVE Binary Tool 是 Python 生态里一个老牌开源漏洞扫描器最初的设计目标是扫描二进制文件里的组件特征不需要源代码。它的原理说起来不复杂从目标文件里提取字符串特征匹配出组件名和版本再把版本跟 NVD美国国家漏洞数据库的 CPE 条目关联最后输出 CVE 列表。后来新版加入了直接解析 SBOM 的能力这一步很关键——如果已经有 SBOM工具连特征提取都省了直接从结构化字段里读组件信息准确率和速度都提升一个量级。我推荐它做 SBOM 扫描几个实际原因。第一安装非常轻纯 Python 包pip 一条命令搞定不像有些扫描器要拉几个 GB 的容器镜像。第二命令行设计直白参数好记适合在 CI 脚本里调。第三输出格式覆盖常规需求JSON、CSV、HTML、SARIF 都有拿去做安全审计报告或者对接漏洞管理平台都没问题。第四它的数据源就是 NVD不依赖第三方平台的私有漏洞库透明性和可追溯性好出报告时能明确标注每条 CVE 引用的数据来源。当然它也有它的脾气。比如它不是全语言覆盖的 SCA 工具对某些框架级漏洞比如 Spring 全家桶的某个配置问题可能不如商业 SCA 灵敏因为它本质是 CPE 版本匹配依赖 NVD 里 CPE 数据的完整度。这个问题后面专门展开讲。1.3 用这个方案之前先搞清楚边界拿 CVE Binary Tool 扫 SBOM并不是所有场景的最优解得先认清它的边界。最合适的场景是你已经有一份 SBOM需要在交付前快速生成漏洞清单或者你的构建流程里能自动产出 SBOM想在提交代码后自动扫一遍又或者你拿到供应商的 SBOM想评估对方组件风险。这几类场景都是输入明确、输出也明确用 CVE Binary Tool 很顺手。不太合适的场景也有。如果你手头只有一个打包好的二进制文件没有 SBOM那更适合让它直接扫二进制目录走它最经典的特征匹配路径而不是硬造一份 SBOM。如果你需要深度追踪许可证合规、版权声明那 SBOM 扫描只能覆盖漏洞部分许可证分析还是得靠专门的工具。另外如果你的项目用到的语言生态比较小众NVD 里 CPE 覆盖不全扫描结果会有明显漏报这个心里要有数。工具是杠杆不是万能钥匙先搞清楚边界再上手后面出了问题才不慌。2. 环境准备与 SBOM 文件获取2.1 安装 Python 环境与 CVE Binary ToolCVE Binary Tool 是 Python 写的所以第一步先确认机器上有 Python 环境。我建议用 3.9 以上的版本太老的版本在新版工具里已经不被支持。用虚拟环境装是常规做法避免污染系统 Python尤其你机器上还跑着别的业务脚本的时候。实际操作如下python -m venv .venv-scan source .venv-scan/bin/activate pip install cve-bin-tool这一步装的是最新稳定版。装完可以先看一眼版本和帮助信息确认命令可用cve-bin-tool --help如果你只想查版本号cve-bin-tool -V我遇到过不少朋友跳过虚拟环境直接pip install然后被系统自带的包冲突搞得焦头烂额。这个工具依赖很多比如 requests、rich、pytest 相关的一堆包跟系统 Python 里已有的包版本撞了特别难受。所以强调一次虚拟环境不是可选项是必选项省得后面浪费时间排依赖问题。安装后不需要额外配数据库工具首次运行时自动从 NVD 拉取数据。不过整个过程可能会持续一段时间取决于网络状况后续会增量更新第一次跑属于一次性成本。2.2 SBOM 从哪来CycloneDX 与 SPDX 两种主流格式做 SBOM 扫描你必须先有一份 SBOM 文件。这个文件的来源分两类别人给的或者自己生成的。别人给的场景很典型你是下游集成方供应商给你一个组件包附带一份 SPDX 格式的 SBOM你要评估这包里的组件风险。这时候拿到的基本就是扫描工具的直接输入不需要另做处理。自己生成的场景更常见。你构建完自己的应用用工具在当前构建上下文里生成一份 SBOM。生成 SBOM 的工具不少我按使用场景区分如果你是 Java 生态可以用 CycloneDX Maven 插件如果你是前端可以用 cyclonedx-npm 之类的包如果你是通用场景想把整个目录扫一遍那 Syft 和 cdxgen 都是好选择。我用得最多的是 Syft因为它的输入很灵活目录、容器镜像、OCI 归档都能吃还能输出 CycloneDX JSON 或 SPDX JSON跟 CVE Binary Tool 配合很顺。用 Syft 生成目录型 SBOM 的方式很简单syft dir:/path/to/your/project -o cyclonedx-json sbom.json容器镜像就是换成syft your-image:tag -o cyclonedx-json sbom.json命令跑完之后会生成一个 JSON 文件里面有一个 components 数组每个组件包含 name、version、purl、type 字段这就是 CVE Binary Tool 扫描时要读取的核心数据结构。如果 syft 扫出来的结果里有大量组件缺失版本字段别急着生成先确认构建产物是否包含了真正的二进制文件而不是只扫到了源码目录里的源代码文件。2.3 拿不到现成 SBOM 时如何现场生成现实里还有一种情况更棘手你要扫描的项目特别老包管理文件都不全更没有 SBOM但客户催着要报告。这时候有两种现场补救办法各有取舍我分别说一下我的经验。办法一从包管理锁定文件直接转。很多锁定文件本身就携带完整的依赖树信息比如 package-lock.json、poetry.lock、yarn.lock、pipenv 的 Pipfile.lock它们虽然没有 SBOM 结构化那么规范但该有的名称、版本、依赖关系都有。可以用 cdxgen、Syft、或 cyclonedx-cli 直接把锁定文件转换成 CycloneDX 格式。比如cdxgen -t javascript -o sbom.json这种方式的优点是快、干净缺点是只覆盖包管理可见的依赖如果有 C 编译期静态链接进产物的组件锁文件里是看不到的。办法二从最终二进制产物反推。如果项目连良好的锁文件都没有就得靠 Syft 直接扫二进制或打包产物目录。对编译型项目来说这一步主要是做特征识别把二进制里可识别的组件特征提取出来生成 SBOM。对解释型项目来说Syft 会尝试读取解释器能找到的包元数据。这个方案的覆盖度比锁文件好但可能引入误识别生成后建议人工抽查一下明显离谱的记录。从热词角度看“sbom生成”确实是目前很多团队卡住的第一步。我的建议是不要追求一份完美覆盖所有边角的 SBOM先把能自动生成的核心清单跑出来后面扫描结果有遗漏再针对性补充。实践中草率的完美主义比粗糙的完成主义低效得多。3. 核心实操三步跑完一次 SBOM 漏洞扫描3.1 第一步确认 SBOM 格式并把工具指向文件拿到 SBOM 之后先确认格式。CVE Binary Tool 对新版参数比较友好直接--sbom接文件路径即可它能自动识别是 CycloneDX 还是 SPDX是 JSON 还是 XML。老版本会区分--sbom SPDXJSON和--sbom-file这类参数新版大幅简化了如果你用的是老版本可以先cve-bin-tool --help确认一下当前包路径的参数写法。最基础的扫描命令长这样cve-bin-tool --sbom /path/to/sbom.json跑完默认在终端里输出结果汇总信息量大致是每条 CVE 的编号、对应组件、CVSS 分数、严重级别。但默认终端输出的信息比较散如果你要在交付材料里用建议指定输出格式和文件。值得注意的一个细节扫描前建议先做一次增量数据更新。CVE Binary Tool 首次运行会下载 NVD 全量数据之后再用默认的缓存策略。如果你手头的工具缓存还是上周的扫出来的结果可能缺失最新公开的 CVE。手动更新命令是cve-bin-tool --update或者直接临时运行cve-bin-tool --sbom xxx时加--update参数先更新再扫我觉得在正式扫描前跑一次更新是值得的成本不高但能避免被验收方拿出最近三天新增的 CVE 打脸。3.2 第二步选择输出格式与过滤条件CVE Binary Tool 支持多种输出格式常用的是 JSON、CSV、HTML、SARIF。不同格式对应不同使用场景JSON 用于自动化程序继续加工或导入旁边的漏洞管理平台CSV 适合丢进 Excel 做筛选和统计HTML 是自包含的单文件适合直接作为交付附件发给客户或安全团队SARIF 则用于对接 GitHub Code Scanning 这类平台。这里我给一个常用组合报告交付用 HTML数据处理用 JSON。一次扫描同时出两种格式不是不可以但命令会重复执行两次等于把漏洞比对跑两遍。更合理的做法是一次扫描产出 JSON再用一个小脚本转成你自己想要的 HTML 或可视化结果。如果只是临时看一眼直接扫一次出 HTML 就行命令cve-bin-tool --sbom /path/to/sbom.json -f html -o report.html如果你不想拿到几百条 low 级别的噪音可以加过滤条件。CVE Binary Tool 支持-s按严重级别过滤比如只看 critical 和 highcve-bin-tool --sbom /path/to/sbom.json -s high -s critical -f html -o report_high.html有的项目有硬性门槛比如 CVSS 低于 7 不修那你还可以设置--cvss 7cve-bin-tool --sbom /path/to/sbom.json --cvss 7 -f json -o result.json这种做法和很多企业漏洞管理流程是一致的先按严重级别收缩范围再进入工单系统派发避免小漏洞把研发团队淹没。3.3 第三步解读 CVE 报告并定位修复优先级拿到 JSON 报告结构大概是每条漏洞都会包含 cve_id、cvss_score、severity、package_name、package_version、cpe、以及 NVD 提供的描述信息。你要重点关注的是 cve_id、package 名、版本和 CVSS 分数因为这就是后续修复动作的依据。我处理报告的思路是三步。第一步按组件分组统计看看哪些组件的问题最多。如果某个组件名下挂了十几条 CVE说明这个组件版本已经严重落后优先升级整体版本而不是逐个补丁。第二步看组件版本和 CVE 的匹配关系。NVD 的 CVE 条目通常会标明影响版本范围比如 1.1.1k这时候你的组件只要是 1.1.1k 就会被命中。但如果某个 CVE 的影响版本写的是1.1.1k而你的版本是1.1.1k-fips这一条可能匹配不上需要手工确认一下版本号的附加字段会不会影响漏洞状态。第三步结合 CVSS 向量判断可利用性。CVSS 分数高不代表实际能被利用尤其在某些内网隔离环境下远程攻击向量的 CVE 可能根本打不进来。我的习惯是把报告里的 CVSS 向量字符串复制出来看攻击向量是不是 network、攻击复杂度是不是 low再结合自己系统的暴露面判断要不要把优先级往上提。这一步很多新人会忽略盯死 CVSS 一个数就去催研发修版本最后研发反问“这个漏洞在公网不可达”你只能干瞪眼。另外报告里如果出现某个组件被标记了 CVE但你在代码仓库里确认过这个组件根本没有被实际调用也不要直接忽略先在 SBOM 里确认该组件的情况如果确实是生成 SBOM 时误收录再去上游修正 SBOM 生成逻辑而不是在报告里偷偷删掉审计不老实比漏洞本身更麻烦。4. 常见问题速查表与避坑技巧4.1 NVD 数据源限流与 API Key 配置我自己第一次跑全量扫描时遇到的第一个大坑就是 NVD 限流。CVE Binary Tool 从 NVD 拉数据NVD 对匿名请求有速率限制数据量大的时候经常中途断掉日志报 403 或者超时。这个问题在后来的版本里通过在工具里配置 NVD API Key 解决。你需要到 NVD 官网申请一个免费的 API Key然后传给工具通常是通过环境变量export NVD_API_KEYyour_key_here cve-bin-tool --sbom /path/to/sbom.json -f json -o result.json工具配置好之后数据拉取的稳定性会好很多。如果你不想申请 Key也没关系只是可能在首次全量拉取或更新频率高的时候比较慢。我个人建议在 CI 环境里把 Key 放到 CI Secret 里避免明文写在脚本里。申请API Key是免费的花五分钟注册一下后面省心很多。还要注意 NVD 的数据同步方式CVE Binary Tool 会先尝试增量更新即只拉取自上次更新以来新增和修改的 CVE。更新依赖一个本地时间戳。如果你长时间没更新甚至换了一台机器时间戳对不上工具会重新做全量同步耗时会明显变长。这属于正常现象等它跑完就行不用反复重启。4.2 SBOM 格式兼容与字段缺失导致的漏报SBOM 扫描看起来是懒人操作但它的质量完全取决于输入文件的准确性。我总结过几个典型的漏报原因你在排查时按顺序检查。一个常见问题是 SBOM 里组件缺少 purl 或 CPE 信息。CVE Binary Tool 解析 SBOM 时核心是拿到组件的 name、version 以及可以用来做 CPE 匹配的 purl包管理器统一资源定位符。CycloneDX 的 components 里如果没有 purl 字段很多组件就变成“裸名字版本”工具只能靠纯字符串去猜 CPE漏报率会大幅上升。如果你生成的 SBOM 里大量组件没有 purl建议先检查生成工具是不是用的旧版本或者输入目录里没有被识别出包管理器信息。另一个常见问题是版本号写法不标准。SBOM 里写的是1.0.0-beta.2NVD 的 CPE 里可能只维护到1.0.0工具拿 beta 后缀去匹配往往匹配不上。这种情况不是工具 bug而是上游数据颗粒度有限。碰到这种组件只能靠人工确认或补一条 CPE 映射。还有一个优先级比较高的坑如果你用 SPDX 格式的 SBOM而且生成工具没有写出 externalRefs外部引用里面同样可能缺失 purl 信息。拿到一份 SPDX 之后先花两分钟搜一下文件里有没有externalRef关键字没有的话得考虑换生成方式。这个细节决定扫描有效性的大半。4.3 误报与假阳性怎么处理误报的来源一般是两条路径。第一条是 CPE 匹配过宽NVD 的某个 CVE 影响范围写成openssl:openssl:1.1.1你的组件名也叫 openssl版本也是 1.1.1但事实上你的 openssl 是某个特定发行版二次开发的版本可能并不受该 CVE 影响。第二条是 SBOM 里有开发态依赖比如构建工具、测试框架被打包进了 SBOM但生产环境根本不部署它们扫出来一堆高危漏洞其实影响不到运行时。处理误报的思路不是直接删 CVE而是先在 SBOM 里确认这个组件到底属不属于生产依赖。如果它属于那就得修如果不属于也要在报告里体现为“非生产依赖”而不是从输出里抹掉。CVE Binary Tool 本身不判断依赖作用域这个判断要你来做可以在报告生成后加一个备注列标注组件类型和在实际环境中的暴露情况。我曾经处理过一个案例生成的 SBOM 里带上了 maven 插件和 devDependencies 的组件扫描结果有几十条 high 级别漏洞但逐条看完之后真正影响生产环境的不超过五条。这时候如果直接把整个报告抛给研发团队他们第一反应就是扫描工具不准后续正常的漏洞你也会被怀疑。所以输出报告之前先人工做一遍上下文标注这对维护扫描流程的可信度非常重要。4.4 扫描速度优化与 CI 集成建议扫描速度主要由三件事决定SBOM 里组件数量、本地 NVD 数据缓存状态、以及网络情况。如果只是扫一个上百个组件的 SBOM通常几秒到几十秒就能出结果。但如果要连续扫多个项目或者在一个没有网络的环境里跑就得提前把 NVD 数据缓存准备好。CVE Binary Tool 有一个离线模式可以在有网的时候先把数据缓存到本机之后离线直接用具体参数查看cve-bin-tool --help我这边不展开细节重点是记住这个思路数据缓存是扫描性能的关键。CI 集成是比较值得做的扩展玩法。很多团队已经能在每次构建后自动生成 SBOM顺手再调一次 CVE Binary Tool 就能在合并代码前发现新增漏洞。CI 里的运行方式和本地不太一样建议每次都跑完整过滤参数来保证输出内容稳定cve-bin-tool --sbom sbom.json -f json -o result.json -s high -s critical --cvss 7然后在 CI 脚本里检查 result.json 里是否还有 critical 级别的 CVE如果有按项目规则决定是失败构建还是仅告警。大部分团队前三个月都只敢告警不敢拦截等扫了几轮没有大面积误报之后再把拦截条件收紧。我个人经验是不要一开始就设成“有 critical 就阻断”先把报告跑两周全组对结果形成共识再逐步收紧不然第一天上线就高亮一串待处理任务谁都会抵触。我实际用了这个方案小半年最大的体会是SBOM 扫描解决的不是“扫不到”的问题而是“扫不全、扫不准、扫完没人认领”的问题。CVE Binary Tool 让扫描这件事变得足够简单简单到每个构建都能顺手跑一次真正难的是让报告的结论跟实际生产环境对得上让修漏洞的任务落到对应的负责人手里。此外还有一个很推荐的做法把生成 SBOM 和扫描做成一个同源流水线构建完直接出报告两个动作绑在一起就不会出现交付物和 SBOM 对不上版本的情况。这套东西跑顺了以后再有人问“你的软件有什么漏洞”你就可以淡定地甩给他一份 JSON 或 HTML 报告而不是说“我回头扫一下看看”。
返回列表