现代的 JavaScript 开发人员都喜欢 npm.GitHub 和 npm registry 是开发人员在查找特定软件包时常去的地方. 开源模块为开发人员提供了很多可在项目中重用的功能, 帮助他们提高工作效率. 可以说, 如果不是这些开源软件包, 今天的大多数框架都不会以当前的形式存在.
一个成熟的企业级应用程序可能依赖数百个 (如果不是数千个) 软件包. 通常的依赖包括直接依赖, 开发依赖, 捆绑依赖, 生产依赖和可选依赖.
然而, 人们通常忽视了存在软件包中的风险. 虽然这些第三方模块在某些方面特别有用, 但也会往你的应用程序中引入一些安全风险.
开源库是否有漏洞?
OSS 软件包确实存在漏洞, 容易遭受攻击. 我们来看几个例子:
最近在一个名为 eslint-scope 的软件包中发现了一个漏洞, 它是一些流行的 JavaScript 软件包 (如 babel-eslint 和 webpack) 的依赖项. 这个软件包维护者的帐号遭窃取, 黑客在其中添加了一些恶意代码. 所幸的是, 有人很快发现了这个漏洞, 最后只影响了少数几个用户.
Moment.js 是用于解析和显示日期的常用 JavaScript 库之一, 最近出现了一个漏洞, 严重性评分高达 7.5. 这个漏洞容易遭受 ReDoS 攻击. 不过他们很快发布了补丁, 问题也将很快得到解决.
5 月份, npm 中出现了一个伪装成 cookie 解析器的后门程序, NPM 在接到投诉后迅速将其移除, 好在没有造成任何真正的破坏.
今年早些时候, GitHub 就开始提醒开发人员他们的代码中包含不安全的库.
GitHub 平台负责人 Sam Lambert 在最近的媒体采访中表示, 他希望能够通过机械化提交的方式来自动化代码提交流程, 从而检测并替换可疑代码.
NPM 安全负责人 Baldwin 在采访中说, NPM 可能会采取类似的措施, 而不只是提供简单的通知.
漏洞太多, 几乎每周都会出现很多新的漏洞. 其中一些很快被发现, 但也有一些在造成严重破坏后才成为头条新闻.
那么我们该如何降低这些风险呢? 在本文中, 我将介绍一些可用于保护开源依赖项的行业最佳实践.
1. 跟踪应用程序的依赖项
从逻辑上讲, 随着依赖项数量的增加, 受到攻击的风险也会增加. 对于直接和间接依赖项来说都是一样的 . 虽然说你不可能停止使用开源软件包, 但对它们进行跟踪总不是件坏事.
要查看这些依赖项十分容易, 可以在应用程序的根目录中运行 npm ls . 你可以使用 -prod 参数显示所有的生产依赖项, 或使用 -long 参数显示每个包的描述摘要.
此外, 你也可以使用服务来自动化依赖项管理过程, 为你的依赖项提供实时的监控和自动更新测试. 一些常见的工具包括 GreenKeeper,Libraries.io 等. 这些工具会整理依赖项列表并跟踪它们的相关信息.
2. 移除不需要的包
随着时间的推移和代码的不断变更, 你可能会停止使用某些软件包, 然后 添加新的包, 但可能不会去删除旧包.
随着时间的推移, 你的项目可能会积累大量不使用的依赖项. 虽然这不会导致 直接的安全风险, 但这些依赖项肯定会增加项目的攻击表面, 并导致不必要的代码混乱. 攻击者可能通过加载具有较高漏洞商数的旧包来查找漏洞, 从而增加造成潜在破坏的可能性.
那么该如何检查这些不使用的依赖项? 你可以使用 depcheck 来完成这项任务. depcheck 会扫描整个代码库, 尝试查找 require 和 import 命令. 然后, 它将这些命令与已安装的软件包或 package.json 中提到的软件包相关联, 并为你提供分析报告. 这个命令也提供了不同的参数选项, 让自动检查不使用的依赖项变得更加简单.
安装 depcheck:
npm install -g depcheck
3. 查找并修复关键安全漏洞
上面讨论的所有要点主要涉及可能会遇到的潜在风险, 但那些你正在使用的依赖项呢?
最近的一项研究表明, 当前有近 15%的软件包包含已知漏洞, 无论是组件还是依赖项. 但是, 好消息是, 你可以使用很多工具来分析代码并发现项目中存在的开源安全风险.
最方便的工具是 npm audit.audit 是随 npm 6 一起发布的一个脚本. npm audit 最初是由 Node Security Platform 开发的, 后来放在了 npm registry 中. 下面是 npm audit 官方博客的一段描述:
安全审计是对软件包依赖项安全漏洞的评估, 可帮助你查找和修复依赖项中的已知漏洞, 从而达到保护软件包的用户的目的. npm audit 命令会将的依赖项的描述提交到默认 registry, 并要求提供已知漏洞的报告.
生成的报告通常包含以下详细信息: 受影响的程序包名称, 漏洞严重性和描述, 路径和其他信息, 以及用于修复问题的补丁命令(如果有). 你甚至可以通过运行 npm audit --json 来获取 JSON 格式的审计报告.
除此之外, npm 还提供了根据报告采取行动的建议. 你可以使用 npm audit fix 来修复已经找到的问题. 这些修复通常使用引导式升级或开源补丁来完成.
4. 使用内部替代方案替换过期的库
开源安全的概念在很大程度上依赖于有多少双眼睛在盯着特定的库 . 越是使用广泛的软件包就越是受到密切的关注. 因此, 开发人员更有可能解决这些特定包中的已知安全问题.
我们来举个例子. 在 GitHub 上, 有很多 JSON web 令牌实现可以与 Node.js 库一起使用. 但那些没有活跃维护者的库可能包含严重的漏洞. Auth0 就报告了一个这样的漏洞, 任何人都可以使用任意有效负载创建自己的 "签名" 令牌.
如果一个很受欢迎的软件包有这样的漏洞, 被开发人员发现和修补的几率会更高. 但是一个不活跃甚至被遗弃的项目呢?
5. 始终选择有人在维护的库
判断一个特定包是否活跃最快最有效的方法可能是在 npm 上检查其下载量. 你可以在 npm 的包主面的 Stats 里找到它. 也可以使用 npm stats API 自动提取这些数字或浏览 npm-stat.com 上的历史统计数据 . 对于具有 GitHub 存储库的软件包, 应该查看提交历史记录, 问题跟踪器以及库的相关拉取请求.
6. 经常更新依赖项
bug 和安全漏洞会不断出现, 在大多数情况下, 它们会立即得到修复.
我们以 2016 年初在 HMAC 软件包 hawk 中出现的正则表达式拒绝服务 (ReDoS) 漏洞为例. hawk 的这个 bug 很快得到修复, 但仅限于最新的 4.x 版本, 而像 3.x 这样的旧版本在很长一段时间后才打上补丁 .
因此, 一般来说, 如果使用最新可用的依赖项版本, 就不太可能存在安全问题.
判断你是否正在使用最新版本依赖项的最简单方法是使用 npm outdated 命令. 这个命令支持是要 -prod 标志来忽略开发依赖项, 而是要 - json 参数会让自动化变得更简单.
定期检查你的依赖项, 验证它们的修改日期, 你可以通过 npm UI 或运行 npm view time.modified 命令来检查依赖项的最后修改日期.
结论
保护应用程序的关键是形成从一开始就将安全放在第一位的文化. 在这篇文章中, 我们介绍了一些用于提高 JavaScript 组件安全性的标准实践.
选择有人在维护的开源依赖项.
更新和监控你的组件.
检查你的代码并编写测试.
删除不需要的依赖项或使用替代项.
使用 npm audit 等安全工具来分析你的依赖项.
工具链接:
- GreenKeeper: https://github.com/greenkeeperio/greenkeeper
- Libraries.io: https://github.com/librariesio
来源: http://www.tuicool.com/articles/qQjMVz2