写点什么

NPM 蠕虫漏洞披露

2016 年 4 月 13 日

NPM 项目已正式承认其存在一个长期的安全漏洞,该漏洞可能导致恶意的代码包可以在开发者系统上随意的运行任意代码,导致了第一个 NPM 创建的蠕虫。在一篇名为“npm 无法限制恶意代码包的行为”的漏洞说明 VU319816 中,Sam Saccone 描述了创建一个蠕虫需要的步骤以及怎么让它自动传播。尽管这是在 2016 年一月被报道出来的,然而从 NPM 仓库管理初始版本发布开始,这个问题就已经存在而且被广泛知晓。

这个问题的根源在于,NPM 模块有相关的脚本文件,它们可以在安装的时候被 NPM 运行。当模块从 NPM 上被下载后,它有足够多的机会可以运行其代码:

  • preinstall - 在包被安装之前运行
  • postinstall - 在包被安装之后运行
  • preinstall - 在包被卸载之前运行
  • uninstall - 在包被卸载时运行
  • postuninstall - 在包被卸载之后运行

这些脚本使得 NPM 模块的发布更加简单并可以在使用之前进行内容的后期处理。举例来说,一些模块原本是由 CoffeeScript 或者 TypeScript 编写的,它们需要一个转化的步骤,或者是用 ES6 编写的,需要 Babel 转化后才能运行在目前的浏览器上。另外,JavaScript 库一般都会进行压缩(使其更小),这往往也是需要自动化运行的一个步骤。因为 JavaScript 是解释性的,像 make 这样的工具不会被使用,所以 npm 脚本就用来干这些苦力活。

在模块被客户端下载和使用的时候,NPM 错误地使用了这些代码,不光用来完成编译时间验证,还进行客户端运行。举例来说, left-pad 惨状(InfoQ昨日报道)在重新发布模块后得到解决;然而,如果像这样被广泛使用的模块(例如 true ,其功能只是打印 true)有被影响的代码块,那么这样的代码运行在成千上万的机器上也有了可能。

这些代码满足了蠕虫的创建条件,然后这些蠕虫持续地影响其他的代码包并依次传播。NPM 包开发者使用标准的证书把他们的代码包(当然是通过 npm)发布到 NPM 目录。为了加快发布,他们有可能会登录到该目录然后一直保持登录状态,此后任何的代码包都可以发布到该目录。正因如此,一旦一个 npm 包开发者的机器被攻占,蠕虫可以扫描其他的代码包,然后重新发布它们(通过开发者现有的证书),与此同时,蠕虫已经被注入到这些刚被感染的包的脚本代码块中。

甚至,包管理其自己也执行 JavaScript,这意味着仅仅是解决包的依赖就会导致任意代码的执行。这里有个例子可以最作为该概念的认证,一个代码包使用变量作为其包名,被发现可以伪装成任何的包。参考真实的开源精神,该概念认证是MIT 证书认证:

复制代码
A="$1"
echo '{
"name": "'"$A"'",
"version": "2.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}' > package.json
npm publish

如果一个包开发者下载了此代码包然后运行了其脚本,那么之后该包会运行 index.js,之后便可以在终端机器上运行任意的代码。该例子就展示了怎样运行 sudo rm -rf /,显然这会在没有任何备份的情况下造成严重后果。

NPM 目录允许任何人重新规划一个存在的代码包,只需要在他们的空间里用相同的命名发布一个新的版本,这使得该问题变得更加复杂。除非开发者特意的写死他们所依赖的代码包版本,否则很有可能自动更新到最近的版本并在之后遭受攻击。

到目前为止 NPM 的回复都相当的软弱,否认了其对扫描恶意软件的责任,并指出开发者使用那些模块受到注入攻击也是咎由自取。然而整个基础都被设置成允许所有人拥有自己的包并可以用任何 JavaScript 替换这些包;尽管这些脚本可以被排除在外(通过使用 using npm install --ignore-scripts 或者 npm config set ignore-scripts true),然而还是有机会使用 require(‘shelljs’).exec(‘rm -rf /’) 替代 JavaScript 文件的内容,其运行时还是有着破坏性的影响。并且,让一个 npm 会话保持登录意味着任何应用,无论是基于 NodeJS 还是其他语言,都可以很容易的在用户不知晓的情况下以当前用户的名义发布脚本。

最近的这些事件表明,随着 JavaScript 的以及服务器端 NPM 使用的快速增长,其被赋予了和 JavaScript 语言本身一样的安全性的考虑。唯一让人感到惊讶的是,整个事件花费了这么长的时间才水落石出。

查看英文原文: NPM Worm Vulnerability Disclosed


感谢张龙对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2016 年 4 月 13 日 19:001653

评论 1 条评论

发布
暂无评论
发现更多内容

架构可视化支撑系统演进探索

华为云开发者社区

架构 软件系统 架构可视化 辅助系统 架构可视化辅助系统

飞桨框架2.0正式版重磅发布,一次端到端的“基础设施”革新

百度开发者中心

2021年金三银四最新美团、字节、阿里、腾讯Java面经,已拿offer!

Java架构之路

Java 程序员 架构 面试 编程语言

三次给你讲清楚Redis之Redis是个啥

华为云开发者社区

数据库 nosql redis hash 字符串

mysql事务隔离的研究

硬核编程

百度应用部署秘籍

百度开发者中心

HugeGraph图数据库获Apache TinkerPop官方认证

百度开发者中心

大牛荐书 | 百度技术大牛都在读的7本书!

百度开发者中心

Linux后台开发面试总结

赖猫

三年Java程序员成功跳槽涨薪,这份《阿里巴巴金三银四Java高级面试题》给了我很大的帮助。

Java架构之路

Java 程序员 架构 面试 编程语言

神级操作:他凭借“Java核心技能精讲”,竟收割了21个Offer

互联网架构师小马

Java 编程 程序员 面试 软件开发

用AI实践继续探索2050全面数字乡村建设

百度大脑

AI

乡村振兴:AI+乡村的下一个命题

百度开发者中心

开放原子超级链动态内核上线,十分钟可搭建一条区块链

百度开发者中心

San介绍以及在百度APP的实践

百度开发者中心

学会 Java 数据结构,想不飘都难

学Java关注我

Java 编程 架构 程序人生 计算机

万万没想到!师兄给我的JVM笔记才是拿下阿里offer的致胜法宝

互联网架构师小马

Java 面试 JVM jvm调优

「开源」首次被列入“十四五”规划,未来大有可为

百度开发者中心

CMS垃圾收集器

张sir

Java JVM 垃圾收集

工作中的设计模式 —— 策略模式

程序员小航

Java 设计模式

超硬核!非科班学生拿下字节跳动offer,只因这份算法笔记

互联网架构师小马

Java 字节跳动 数据结构 面试 算法

终于有腾讯架构师把困扰我多年的《计算机网络原理》全部讲明白了

云流

Java 架构 网络 计算机 程序员·

5G 和云原生时代的技术下半场,视频化是最大最新的确定性

阿里巴巴云原生

人工智能 云原生 5G 存储 调度

面试官:什么是死锁?怎么排查死锁?怎么避免死锁?

互联网架构师小马

Java 面试 死锁

5年crud经验,三个月啃透888页Java王者级核心宝典,竟翻身阿里p6

Crud的程序员

Java 编程 架构 java面试 Java工程师

月薪30K以上的C/C++Linux后台服务器开发学习路线是怎样的?

赖猫

c++ Linux 后台开发 后端

Impala简介以及与Hive的异同

五分钟学大数据

4月日更 impala

一不小心,它成为了 GitHub Alibaba Group 下 Star 最多的开源项目

阿里巴巴云原生

Java 微服务 云原生 dubbo Arthas

软件测试面试题【2021模拟面试整理版(含答案)】

程序员一凡

面试 软件测试

github访问速度很慢-一招完美解决,小伙伴们赶快get起来吧!

再见孙悟空

GitHub github访问 github打开慢 github.com github打不开

为什么 MySQL 不推荐使用 join?

互联网架构师小马

Java MySQL join

演讲经验交流会|ArchSummit 上海站

演讲经验交流会|ArchSummit 上海站

NPM蠕虫漏洞披露-InfoQ