标题:ShellShock:小心bash里的大坑 出处:Felix021 时间:Sat, 27 Sep 2014 00:55:35 +0000 作者:felix021 地址:https://www.felix021.com/blog/read.php?2138 内容: #update@09.28 注意,根据CoolShell这篇文章指出,官方的patch25并没有真正解决问题,仍然可以使用这种方式来实现注入(具体解释详见那篇文章): $ env X='() { (a)=>\' bash -c "echo date"; ,经过测试,Ubuntu官方更新的Bash不受影响,但是自己patch的bash还是不能解决这个问题。 大概大家都知道了,最近bash爆出来了个大漏洞,名号ShellShock,影响范围是bash 1.14 ~ 4.3(最新版),基本上你能想到的Linux/Unix机器都中招了,包括果粉们的macbook。 当然有些人还是心怀侥幸,那么就执行下面这个命令试试看: $ env x="() { :;}; echo vulnerable" bash -c "echo this is a test" 如果输出是:引用 vulnerable this is a test 恭喜你中奖了,bash将环境变量的定义直接执行了,说明被注入了。 而打过补丁的系统里,输出应当是:引用 bash: warning: x: ignoring function definition attempt bash: error importing function definition for `x' this is a test 解决方法其实很简单,大多数发行版都迅速针对这个问题推出了安全更新,比如常用的ubuntu,只需要在 sudo apt-get update 以后运行 sudo apt-get install bash 就可以了。redhat什么的也类似,网上搜一下就能找到相应说明。 而对于raspberry pi或者是mk802这种就比较蛋疼,ports.ubuntu.com 还没有及时更新,因此只能手动打补丁了: 【UPDATE】patch-25并没有完全解决问题,可以在另一个ubuntu下apt-get source bash来获取完全免疫版本的源码 #!/bin/bash mkdir bash-patched cd bash-patched wget http://ftp.gnu.org/gnu/bash/bash-4.3.tar.gz #download all patches for i in $(seq -f "%03g" 0 25); do wget http://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-$i; done tar zxvf bash-4.3.tar.gz cd bash-4.3 #apply all patches for i in $(seq -f "%03g" 0 25);do patch -p0 < ../bash43-$i; done #截止到2014/9/27最新的patch编号是25 #build and install ./configure --prefix=/ make && make install 打完补丁心里放心了,就可以来安心看看shellshock是怎样影响到你的系统的。 一个最简单的例子是CGI(Common Gateway Interface),最早的动态页面都是通过CGI实现的:http server除了给出一些CGI中规定的环境变量之外,还有解析HTTP Header中的字段,加上前缀HTTP_也设置为环境变量;准备好env以后,才去调用对应的CGI程序,CGI程序通过解析变量的值来获取用户的输入,并给出相应的返回。 比如说Ubuntu上的apache,默认是开启了mod_cgi,并且cgi目录是 /usr/lib/cgi-bin ,我们可以在下面放一个最简单的cgi脚本,名叫 test (并chmod +x),其内容是 #!/bin/bash echo #输出一个空行,用来分隔httpserver的HTTP Header和下面的HTTP Entity echo "Hi" 访问 http://127.0.0.1/cgi-bin/test ,你就可以看到一个页面,内容是Hi。你可以在CGI程序的末尾追加一个env命令,用来查看环境变量,可以看到诸如REQUEST_URI、REMOTE_PORT之类Server自动填充的内容,也可以看到HTTP_USER_AGENT之类浏览器添加的内容。 注意,浏览器可以影响到(这个cgi脚本及其子进程的)环境变量——这就是突破点了,因此可以很容易地构造一个攻击请求,让服务器执行指定的命令,例如: 引用 $ nc 127.0.0.1 80 GET / HTTP/1.1 Host: 127.0.0.1 X: () { :;}; echo ""; cat /etc/passwd 服务器返回的内容就变成了:引用 HTTP/1.1 200 OK Date: Fri, 26 Sep 2014 16:52:21 GMT Server: Apache/2.2.22 (Ubuntu) Transfer-Encoding: chunked 455 root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh ... username:x:1000:1000:username,,,:/home/username:/bin/bash 经过我的测试,php-fpm和apache的mod_php方式都不不受shellshock的影响,但是不要认为你没有跑上面这种CGI程序就放心了,例如常见的基于CGI的perl和php(据说fastcgi没问题,但我没测试),有时会通过system之类的函数调用shell命令,这也会导致bash被调用,而且据说openssh和dns client也有类似的问题(具体情形我没有了解),所以就不要侥幸了,尽快升级你的bash吧! p.s. 说一句马后炮的话,这个BUG实际上非常简单(以至于我这么容易就弄懂了),bash遍历环境变量的时候会(用yacc生成的解释器)检查它的值,如果它看起来像是一个函数的定义(就像 x="() { echo hello!; }" 这样),那么bash会eval这段代码,然而如前面的例子所示,虽然它看起来像是一个函数定义,但是它实际上可以是用分号分隔的多个语句,依然满足bash的语法……看了一下bash43-025这个patch,修改了几十行,主要就是增加了 SEVAL_FUNCDEF 和 SEVAL_ONECMD 两个类型以及相应的用于进一步区分环境变量的检测代码,从而避免了上述情况。 Generated by Bo-blog 2.1.0