2006年秋天,Google 认为要运行现代 Web 应用,浏览器必须有一个性能非常强劲的 Java 引擎,于是开发了一个高性能的开源 Java 引擎,名为 V8。
两年后,V8 与 Chrome 在同一天宣布开源
2009年,Ryan 正式推出了基于 Java 语言和 V8 引擎的开源 Web 服务器项目,名为 Node.js。
从此 Java 也可以在后端服务器开发,由于已经有很多的 Java 开发人员,所以Node 很快流行起来了。
Node.js 可以安装在 Linux、Mac、Windows 平台上,NPM 其实是 Node.js 的包管理工具,它可以让开发人员方便的安装、卸载 js 模块,自动解决依赖关系。
But!每个基于 Web 或 Node 应用开展工作的人,总会遇到这样的情况:
由于受到 event-stream 依赖项攻击,用户 copay#9346 的钱包丢失了。
这种关于加密和安全的新闻数不胜数,它们根本上质疑着我们使用 Node.js 构建开源软件的方式。
基于此,我有以下解决方案:
接下来,我会分别从典型案例分析、开源、更新问题和 NPM 模块安全4方面告诉你我是如何得出以上5点结论的。
一个典型的 Node.js 生态问题案例
不妨看看 GitHub 和 NPM 的 event-stream repository 案例:
7年前,开发者 dominictarr 创建了一个名为“event-stream”的NPM模块,这是一个容易创建和使用 stream 的工具包。它非常受欢迎,周下载量接近200万:
周下载次数 1911379
两个月前,在经历了82个版本更新之后,最新版本 4.0.1 发布了。令人意想不到的是,发布者不再是 dominictarr,而是一个名为 @ right9ctrl 的黑客。
对于黑客来说,目的不在于「轻松创建和使用stream」,而是「窃取用户所有的加密货币」。
没有人会自愿使用这样的模块,所以黑客将代码做加密处理,并利用 event-stream 模块已有的信用和品牌,将恶意代码隐藏到数百万个其他项目中。
那么黑客是如何盗取官方NPM账户的?他们入侵了 dominictarr 的帐户?还是敲诈勒索了他?他被黑客用枪支胁迫后泄漏了证书?
不,都不是,仅仅是一份邮件足矣!dominictarr 通过这份邮件得知了黑客的需求,然后将这个每年有着1.12亿新增用户模块的完全控制权给了黑客。
他发邮件告诉我,他想要 event-stream 模块的控制权,然后我就给了他。
我没有得到任何利益,我甚至好多年都没有使用这个模块了。
许多开发人员因意识到他们时刻处于危险之中而感到不安,他们的用户已经失去或将来会失去他们的金钱:
因将控制权给予黑客导致上百万用户受害,往往原始开发者会拒绝承担责任。
由于来自外部的巨大压力,原始开发者在2天前发布了一份官方声明:
嘿,大家好!请注意,这不是一件小事情。 你的依赖树中还有很多其他模块,它们已经成为原始开发者的负担了。 我当时并不是因为利他动机而选择敲下了这些代码,纯粹是觉得好玩儿,一切都为了精神上的自我满足。 但随时间推移,它慢慢变得不再有趣了,我就得不到相应的回报,所以不会再去花费精力维护它。 如今,我们正处于一个非常难受的境地,原始开发者对自己「产品」已失去兴趣、甚至逐渐倦怠,他们勉强地维护着这些无趣的东西,而且自己也早已不再使用了。
很幸运,我找到了两个有力的解决方案: 1)给予维护者一定的收益;2)亲自参与维护。
开源有罪吗?
除了互联网行业,我还没有看到其他任何一个行业,大量工作是免费的,开源开发者们经常这么做。
他们要么为了“乐趣”,要么是想得到某些“反馈”,因为他们知道,如果没有开源软件,很多事情就不会成为现实。
但是,我们对开源项目有着与付费软件相同的责任和期望。开发人员和维护人员经常因“不做”工作或未“及时”回应而受到骚扰。同时,我们忘记了大多数开发者都在按照自己的时间表工作,也许敲代码并不是他们的主业,他们从事着其他行业,并希望与家人一起生活,那么“及时”就不存在了。
人们常常忘记他们不欠任何人的任何东西。
维护需要花费巨大的精力与成本,这就是在付费软件行业中通过维护赚取大量资金的原因。
但我们忘了 npm install-cat-ascii-faces --saveis 不包括通过一次“购买”就有要求终身维护服务的权利。
更新问题
一旦关键数据指标或收益下降,相对于为最后100或1000名铁杆粉提供优质服务,停止管理一个项目要容易得多。每个人都必须清楚,那些已停止更新的项目,有着大规模的安全问题。
对于这种现象,Electron 核心开发人员 Paul Betts 这样说:
开发软件很容易、扔掉也很容易,难题在于如何维持软件的更新与活力
每次都获得正确的更新是极其困难的。
具有讽刺意味的是,目前用于构建最流行的代码编辑器和加密钱包的 Electron 框架,在其自身依赖关系上存在着大量问题。许多依赖 Electron 的应用程序,仅仅是因为安装后没有及时更新,就将数百万用户置于危险之中了。
但即使你经常更新软件,又如何阻止恶意 NPM 程序包潜入应用程序的代码库呢? 我还没有检查它,但如果 event-stream 被用在非常流行的应用,例如 VS Code,它可以很容易地升级到完整远程代码,然后执行 RCE 攻击。
拥有完整的主机系统,就好像黑客正坐在你的面前,肆意操作键盘、鼠标、文件系统,相机等。
攻击场景不仅限于从加密钱包中窃取财产。
NPM 模块安全
今年12月初,我在以太坊 Devcon 4 大会上发表了关于浏览器和钱包安全性主题的演讲。其中就有一张幻灯片是讨论过去基于 Electron 应用的攻击向量和成功攻击实例。
该幻灯片基于 Luca Carettoni 提供的 Electronegativity 黑帽演示和威胁模型:
NPM 模块给予了黑客巨大的攻击便利,就在3周前,我向人们发出警告的同时,另一起攻击就正在发生。NPM 或依赖安全性对于 Electron 或 Node.js 来说并不是一个特定的问题。它也不是新的或未知的。
不幸的是,它也不会被新的审计功能解决,而且也无法通过更好的AV集成、扫描、AI 或漏洞检查以及 GitHub 上的标记来解决。
如何修复 Node.js 生态系统?
dominictarr 进行了这样的描述:
开源是由共享驱动的!这很棒!在比特币受欢迎之前,它确实运作良好。
区块链技术是一个很好的解决方案,为创建一个更好的生态系统,我们可以从以下两方面着手:
一般情况下,在传统场景下完成这两件事是很困难的,但通过区块链技术就可以做到几乎免费获得它们。
那么,如何借助区块链技术修复Node.js生态呢?
假设有一个使用开源模块且使用区块链技术进行应用内付款的项目。就像 event-stream 案例中那样,众多依赖项中的某一个可能会成为恶意程序包。
但原始开发人员不会向新协作者提供完全维护权或完全发布权,而只会为新维护者或 CI 系统提供签名权。所以新开发者会在他们发布的版本上签名,而原作者经过仔细的审查后,会附签声明,表示他检查并批准了这些更改。
随着各个版本的发布和签名,新开发者的签名将会获得更多信任。
但如果某些事情经过审计并被标记,则可能会受到经济处罚等。
如果收到来自安装此模块软件的付款,运行环境中可能存在以下逻辑:基于此开源代码的影响或贡献,自动将每笔付款的几美分分配给模块作者。
不要小看这几美分收益,每年接近1.12亿次的下载量足以累积成巨大财富,这些收益可以用来激励开发者参与其他项目的维护。
虽然听起来有些过于理想,但也许实际上已经拥有了,我们应尽快到达那里。
其他签署模块的项目已开始基于 PGP 密钥并采用此标准,这听起来是符合逻辑的下一步骤,该标准在其他软件领域已经是一种常见的做法。
我非常确定,即使以后会有更多、更好的改进方案,但签名和支付方案很快就会成为现实,并帮助 Node.js 生态系统创建更高质量的代码,并激励更多的开源开发人员做出贡献,因为我们非常需要它们。
— END —