Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

你要知道的 npm 依赖包漏洞检测和修复 #69

Open
Luin-Li opened this issue May 12, 2022 · 2 comments
Open

你要知道的 npm 依赖包漏洞检测和修复 #69

Luin-Li opened this issue May 12, 2022 · 2 comments

Comments

@Luin-Li
Copy link
Contributor

Luin-Li commented May 12, 2022

依赖包漏洞扫描的工作流程大致如下图,通过这个图我们先对整个过程有个粗略的印象。本文会先扫扫盲,介绍一些常见的名词,然后再介绍几个漏洞扫描工具,最后以其中一个工具作为示例,介绍如何进行 npm 依赖包漏洞检测和修复。

流程图

与漏洞有关的常见关键词

CVE

CVE是通用漏洞披露(Common Vulnerabilities and Exposures) 的简称,是一个记录常见漏洞的资料库。CVE对每一个漏洞都会有一个专属的编号,格式为CVE-YYYY-NNNN。YYYY为漏洞披露年份,NNNN为流水编号。如下图为CVE各个年份记录的漏洞数:

CVE

CVSS

CVSS是通用漏洞评分系统(Common Vulnerability Scoring System) 的简称。CVSS 提供了对漏洞进行打分的标准,是一个打分系统。CVSS 首先从各个维度对一个漏洞进行度量,然后综合各个度量值得出一个分数,分数越高越严重。以v3.1标准来说,CVSS的评分有三个指标组,基本分、时间分和环境分。

基本分:代表每个漏洞的固有特征,度量值包括攻击向量(AV)、攻击复杂度(AC)、权限要求(PR)等, 共8个。如下图,基于各度量值所得的基本分为6.4:

基本分

时间分 :由于外部的事件随时间变化的漏洞特性,共3个度量值。时间分是在得出基本分的前提下,对漏洞进行更进一步的打分。如下图,在基本分为6.4的前提下,若修复水平(RL)为官方修复(O),则时间分为6.1:

时间分

环境分:反映漏洞与用户环境相关的危害性,共11个度量值。环境分是在得出基本分和时间分的前提下,对漏洞进行再进一步的打分。如下图,在基本分为6.4和时间为6.1的前提下,若保密性要求(CR)为L,则环境分为5.5:

环境分

每个指标综合各个度量值根据公式,计算这个指标的分数, 公式计算方法在这里,有兴趣可以看看。漏洞的基本分可按分级标准可进行定级(例如低,中,高)。如下图为该系统两个不同版本(v2.0 和 v3.0)的分级标准:

cvss2-3

如下图示例,对于漏洞CVE-2013-0375:MySQL Stored SQL Injection的评分,两个版本的度量值有所差异,得出的分数也不同,基于 v2.0 标准评分为5.5,基于v3.1 标准评分为6.4。

cvss2vs3 1

CWE

CWE是通用缺陷列表(Common Weakness Enumeration) 的简称,是一个对软件脆弱性和易受攻击性的分类系统, 提供了一份软件弱点类型列表,(CWE的角色个人觉得可理解为类似 HTTP 状态码)。如下图部分弱点分类:

CWE部分

CPE

CPE是通用枚举平台(Common Platform Enumeration) 的简称,是一种标准化方法,用来描述漏洞影响了哪些应用程序/组件的哪些版本。格式形如 CPE:2.3:类型:厂商:产品:版本:更新版本:发行版本:界面语言:软件发行版本:目标软件:目标硬件:其他 (2.3为CPE的版本), 例如cpe:2.3:a:*:react-dev-utils:\>\=0.4.0\<11.0.4:*:*:*:*:*:*:*

国家漏洞数据库

NVD 是美国国家漏洞数据库(NATIONAL VULNERABILITY DATABASE) 的简称,创建于2000年。

CNNVD 是中国国家信息安全漏洞库(China National Vulnerability Database of Information Security) 的简称,于2009年10月18日正式成立。

如下图,以 CVE-2021-46101 这个漏洞在 NVD 和 CNNVD 的记录为例,在 NVD 中会展示该漏洞的 CVSS 基本分、所属的 CWE 类别和涉及的 CPE 信息。

nvd

扫描工具

依赖包漏洞检测的开源工具和软件比较多,这里不展开详细介绍,本文只介绍三种 npm 包自动化检测工具npm auditsnykDependency-Check

npm audit

npm@6.x 新增 npm-audit 命令。npm audit的漏洞数据来自 GitHub Advisory Databasenpm audit 扫描依赖于 package.json 和 package-lock.json 文件,如果没有这两个文件会报错。执行npm audit命令后,会输出如下图的安全报告,报告存在漏洞的依赖包信息。可以执行npm audit fix进行修复,对于非兼容性的依赖包升级需要执行npm audit fix --force

npm-audit

Snyk

Snyk是 一家美国的安全公司,帮助开发者们在开发阶段就能查找、修复和监测代码的脆弱性。Snyk 维护自己的开源漏洞数据库。Snyk 可以直接登录 github 账号,然后选择要扫描的仓库。如下图,扫描了我仓库下的EasyProvuePro项目,扫描结果显示vuePro项目下有漏洞。其中,npm 包涉及的漏洞有四个(一个高危三个中度)。

synk

点击查看漏洞详情,如下图,显示其中3个漏洞均来自axios@0.16.2,一个漏洞来自async-validator@1.4.13

synk-npm包漏洞

Snyk 让我觉得眼前一亮的功能是,针对这些依赖包漏洞,能够自动提交 PR(Pull requests),如下图,一顿点击猛如虎后,Snyk 提交了一个 PR [Snyk] Security upgrade axios from 0.16.2 to 0.21.3到我的项目中。

synk自动pr

Dependency-Check

Dependency-Check 是 OWASP 的一个实用开源程序,基于 NVD 漏洞数据库检查项目依赖项。它主要用于扫描 Java 和 .NET 代码。另外它也支持扫描 Python,Ruby,PHP(Composer)和 Node.js 代码,但这些语言的扫描都是实验性的,可能会有误报。

Dependency-Check 通过收集扫描依赖包的信息来发现漏洞,收集的信息称为 Evidence , 包括三种提供者信息、依赖包名称和依赖包版本 (vendor、product、version) 。通过 Evidence 和 CPE条目进行匹配,匹配到了就会给个标志发送到报告中记录一个依赖包漏洞。对于前端npm包的扫描,与npm auditsnyk不同,它不依赖package.jsonpackage-lock.json的信息,Dependency-Check 是直接扫描文件夹下存在的依赖包, 然后输出一份 .html 格式的漏洞报告。

实践:基于 Dependency-Check 的第三方包漏洞检测并修复

下文将以 Dependency-Check 命令行工具为例,详细介绍如何扫描一个前端项目中的依赖包漏洞,并根据报告进行漏洞修复,即对npm包进行指定版本升级。

1. 下载 Dependency-Check 工具

下载 Dependency-Check 命令行工具

tips:运行前要准备好 java 环境,如果没有,会爆错。 java 安装可以参考这篇

2. 执行命令,生成报告

解压后, 执行命令:

cd bin
dependency-check.bat --disableNodeJS --project test -s F:\chop\rr\rr-app -o F:\chop\rr\rr-app\dependency-check-report
  • --project:工程名称
  • -s:要扫描的文件夹
  • -o:结果输出路径
  • --disableNodeJS:不检查 nodejs

运行命令后,工具会先开始下载各个年份 NVD 漏洞数据库,如下图:

download-nvd

如下图,下载完成后开始扫描,并将扫描结果输出到指定的路径中。

analysis

如下图,在第一次扫描后,会将下载的各个年份的 NVD 漏洞数据库缓存到工具 data/nvdcache 的文件夹中。当再次扫描其他项目时,会校验数据库是否有更新,如果没有更新,会从缓存读取 NVD 漏洞数据库数据,然后直接开始扫描不需要重新下载。

nvd-cache

3. 解析报告

报告主要包括三个部分:

基本信息: 包括项目名、工具版本信息,依赖包数量和有漏洞的依赖包数量。

基本信息

Summary: 以表格列出所有有风险的依赖包版本、风险等级、涉及的漏洞数量和Evidence数量。

summary

Dependencies: 每个依赖包涉及的漏洞的具体说明。如下图,以ansi-html@0.0.7这个依赖包为例,

漏洞详情

4. 调整npm包版本

发现漏洞后升级 npm 包版本,乍一听好像并不困难,但是有两个问题需要考虑: 1)升级到哪个版本;2)针对非直接引入的依赖,如何锁定版本。

升级到哪个版本?

虽然漏洞报告已经很清楚描述了漏洞涉及的版本以及每个漏洞修复的版本,但是为了更加精确且开发成本最小地升级到没有任何漏洞的版本,我们可以借助 snyk 网站进行查询,找到适合自己项目的版本进行安装。因为在实际项目中,我们不仅要考虑该版本是否有漏洞,还要考虑配置兼容性等问题。 例如,报告显示 webpack-dev-server@2.11.5 存在漏洞,通过查询我们得知, 至少要升级到大版本 webpack-dev-server@3.1.11 才能“完全”没有任何漏洞,但是 webpack-dev-server@3+ 是基于webpack@4+的,所以如果项目是 webpack@3+ 也要升级大版本。

webpack-dev-server漏洞

当然,上面说的要升级大版本的问题,是因为 webpack-dev-server@2+ 后面没有出一个 hotfix 的小版本修复这个漏洞,(偏一下题,为啥没有针对这个漏洞的 hotfix 小版本呢?我找到的官方答复有兴趣地可以瞅瞅)。有些 npm 包针对低版本的漏洞会出 hotfix 小版本去修复漏洞,那我们就可以借助这个网站查到对应版本,快速地进行小版本升级。

BTW:上面截图的针对某个 npm 包各个版本漏洞信息的表格,暂时没找到入口,但是我发现可以直接修改链接地址进行查询,类似这样https://snyk.io/vuln/npm:${npm包名},以上图webpack-dev-server为例。

针对非直接引入的依赖,如何锁定版本?

1)整理想要指定版本的依赖,在 package.json 中新加 resolutions 字段。

对于非直接引入的 npm 包,除了指定安装版本外,有时候因为原代码库不再维护等原因,我们希望替换包,也可以放在这里配置。如下配置为,将 ansi-html 替换成 ansi-html-community 和将 acorn 锁定版本 v7.4.0

"resolutions": {
  "ansi-html": "http://190.xx.xx.xx:xxxx/repository/npm-group/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
  "acorn": "7.4.0",
}

2)在 package.json 中的 scripts字段增加 preinstall, 它作用是在运行 npm install 前就会先自动运行 preinstall 指令,生成新的package-lock.json

{
  "scripts": {
    "start": "node scripts/start.js",
    "build": "node scripts/build.js",
    "test": "node scripts/test.js",
    "preinstall": "npm install --package-lock-only --ignore-scripts && npx npm-force-resolutions@0.0.3"
  },
}

3)删除项目已有的package-lock.jsonnode_modules文件夹, 运行npm install,如下图,为锁定前后这两个包的package-lock.json信息。

锁定前

锁定后

4)通过以上步骤后,其实我们已经生成锁定版本的package-lock.json,为了避免再次安装的时候,再走一遍这样冗余的流程,其实我们可以将 [步骤2] 新加的 preinstall 字段去掉。

--

参考资料

DependencyCheck官网

CWE中文列表

通用漏洞管理与SCAP

@Hibop
Copy link
Contributor

Hibop commented May 22, 2022

👏 👏 👏 NVD 这个爆的漏洞比较权威。
snyk 网站进行版本查询,,对于生产环境, 锁版本是个很好的方案,便于定位以及跨环境;

其实对于漏洞修复, 除了被动官方的升级;还有一个主动修复方案就是,自己打patch修复,可以了解一下,很多时候可能就几行代码, 但是等官方升级 猴年马月@Luin-Li

@Luin-Li
Copy link
Contributor Author

Luin-Li commented May 24, 2022

clap clap clap NVD 这个爆的漏洞比较权威。 snyk 网站进行版本查询,,对于生产环境, 锁版本是个很好的方案,便于定位以及跨环境;

其实对于漏洞修复, 除了被动官方的升级;还有一个主动修复方案就是,自己打patch修复,可以了解一下,很多时候可能就几行代码, 但是等官方升级 猴年马月@Luin-Li

get!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants