最近的 ESLint hack 或者我们如何保护自己免受安装恶意 npm 包?

信息安全 证书 节点.js 包管理器 npm
2021-09-03 21:08:34

最近,eslint-scope软件包eslint-config-eslint以一种有趣的方式被黑——维护者的一个账户被攻击者入侵,一个带有恶意代码的新“补丁”版本被发布到 npm 注册表。

此恶意代码作为“安装后”脚本执行,并试图从站点评估某个 JS 代码,并从本地文件pastebin中窃取 npm 身份验证令牌,并将其发送到标头内的端点更多攻击细节可以在这里找到。有趣的是,这个问题是因为恶意代码实现中出现语法错误而被发现的。npmrchistatsstatcounterReferer

考虑到 ESLint 团队花了几个小时来解决这个问题,很多 npm 身份验证令牌被盗,这意味着将来其他包可能会以同样的方式受到污染。

作为 npm 用户,我们如何在从 npm 注册表安装依赖项时保护自己免受未来类似的黑客攻击?

3个回答

三个字:供应链管理除了在我们的例子中,“供应”是依赖或“第三方库”。

这不是 npm 独有的问题。这是软件开发中的普遍问题。这相当于在谷歌上搜索“螺丝”制造商,然后使用您看到的第一个“螺丝”制造商,不要询问“螺丝”的规格,然后使用这些“螺丝”并希望他们能做到工作正确,不会断裂,腐蚀/生锈太快,并且可以承受压力......无需检查这些螺丝是否经过测试,是否有适当的质量控制。我们可以这样做,因为如果您的软件有缺陷或易受攻击,通常不会有人死亡。如果一个结构因为螺丝有问题而倒塌......那是另一回事。那里有责任。软件中没有这样的责任......除非你' 如果您的控制软件有错误,则在发生软件错误或巨大而昂贵的机器损坏(和/或危及生命)时实际上危及生命的一些行业重新工作。我的意思是死得很严重。如果您必须能够支持实时通信以实时控制某些进程,并且如果您使用的第三方库产生CPU故障,因为它有问题......因为那样你的机器就会真正损坏。

软件开发的问题是我们“谷歌”搜索“一些库”提供“一些功能”,然后我们只是“npm install”、“go get”、“pip install”它,我们很高兴。那里没有验证过程。你怎么知道这个包提供了它声称的东西?你知道它的测试效果如何吗?你知道它是否还在积极维护吗?你知道什么是 API 稳定性保证吗?你可以“去获取”一些包,一周后包就完全坏掉了,因为即使是“官方”的 go 代码也可能没有任何 API 稳定性保证。

您使用什么版本约束?foo >= 1.5. 如果foo >= 1.6引入后门怎么办?使用最新版本编译您的代码的人将在其中包含此后门。如果您使用foo == 1.5但有不同的镜像并且您的同事用于构建您的软件的镜像包含该软件包的恶意版本怎么办?并且不要忘记:如果您安装/使用包/库?您不仅需要验证该包/库...您还需要验证整个依赖关系树

我们需要的是一个认证过程。一旦公司/开发人员认为他们的包准备好了,他们就会发布它,然后独立的代码审查和安全公司审查包,一旦有合理程度的信心认为这个包是“安全”的,他们就会签署它。然后,您只能使用已签名的依赖项,并且除了使用foo == ("1.5", "abc734defef373f..").

您如何将其应用于 npm?

不要在没有审查的情况下安装 npm 包。作者是谁?一般的代码质量如何?最后一次更新是什么时候?最近的几次提交是什么?它的安装有什么作用?它有适当的测试吗?代码/测试覆盖率是多少?有多少人在使用它?谁在使用它?

软件开发的重点是提供更新、新事物、更新、新事物。适当的测试和适当的“第三方代码管理”成本很高,而且大多数情况下公司和消费者都不愿意支付这个价格。毕竟,这始终是“风险与成本”。如果安全漏洞的代价是某些用户窃取了他们的凭据......没人在乎。他们不能起诉你。在最坏的情况下,这会让你在“公众形象”方面付出一些代价。如果最糟糕的是一个对某些用户不起作用的有缺陷的软件......你可以承受一些使用免费版本的用户的愤怒......如果有像“保修”这样的东西,这可能会改变

在您的网站上使用第三方 javascript 也存在此问题。一样。无论您使用什么语言、框架、技术,问题几乎完全相同:如果您想要安全……您需要验证第三方代码。

另一件事:

有些包/库只提供很少的实用程序......你可以在 3 小时内自己编写的东西......也许一天。如果您不关心更多的依赖项(并且更多的依赖项会使您的依赖项管理复杂化),这不是问题,但是如果您这样做......有时实际上不使用这些简单的库并自己编写功能会更省力,这样你可以完全控制它并且可以正确地测试它。经验法则是,如果您验证别人的代码所花费的时间比您自己编写代码所花费的时间长……那么您自己编写。如果您只需要整个框架中的一个或两个函数,这也适用。它'

除此之外:......您可以在安装过程中阻止到非白名单网站的流量,这意味着这种特定的攻击将不起作用,但不适用于仅删除随机文件或插入后门的恶意安装脚本现有文件或其他任何东西。您必须仔细阅读安装脚本。

供应链管理在理论上是正确的答案,然而,尽管像 snyk 和许多其他商业实体的努力,在实践中节点生态系统中并没有解决这个问题。

Node 的供应链记录,并没有对众多努力使其变得更好的人不敬,是非常糟糕的。那座臭名昭著的山之王曾经是 wordpress 模块,但至少在过去的几年里,它现在已经成为节点。安全失败只是做生意的代价。

理论上你可以:

  • 在安装之前阅读所有依赖项的代码
  • 阅读其依赖项的所有代码
  • 安装在带有服务器白名单的沙箱中
  • 白名单依赖项,需要几周或更长时间的烘烤期
  • 引入漏洞源、扫描器和分析器
  • 假设节点工程师工作站总是受到威胁,使用机密管理并且不允许他们查看密码,或直接访问生产系统或数据
  • 有一个 CI/CD 可以在宣布修复时找到并重新部署所有使用特定依赖项的应用程序

或者你可以完成一些工作,并希望最好,直到生态系统改善(最终会改善)。

基本上这里的问题是第 3 方软件试图窃取私人信息并通过网络发送出去。这个问题不是 npm 独有的,任何以您的计算机用户身份运行的软件都可以这样做,因为没有什么可以阻止它读取您的用户数据。

在此处输入图像描述

作为抵御此类攻击的一道防线,您可以考虑使用出站防火墙。

有许多这样的产品,主要是商业产品,但是对于相当知名的 Little Snitch(我不隶属于它),如果 Node 进程尝试连接到防火墙尚未配置为授予权限的主机访问时,将提示用户决定是否应允许建立该连接,如下所示:

在此处输入图像描述

自然,如果您在安装 npm 模块时看到类似的情况,它应该会触发一些危险信号,此时您可以通过拒绝访问来阻止它,直到您审核此连接的来源。

显然,这不能替代审计源代码,但它确实提供了额外的一层防御,防止流氓软件试图在整个系统范围内泄露你的私人数据,并且可能非常有效地阻止这样的攻击(假设你没有' t 给二进制文件攻击使用过大的权限)。