努力, 努力, 再努力
全部博文(220)
分类: 网络与安全
2015-04-21 11:15:38
Bash 漏洞的起因,修复,验证与分析
一. Bash漏洞的发现
1. 漏洞的发现与追踪
a)2014年9月24日,国外媒体爆出一个广泛存在于Linux系统中的bash软件漏洞,并称之为: shellshock,国内中文名为:”破壳”,CVE漏洞编号: CVE-2014-6271
b) 2014年9月25日,GNU Bash官方发布解决补丁,随后不久,国外安全研究员称已经绕过该补丁,从而导致该漏洞一直处于未修补状态
c) 2014年9月26日,红帽安全团队感到漏洞的危害性,为shellshock漏洞的绕过创建新的漏洞编号 CVE-2014-7169,同时发布新的补丁。
d) 2014年9月27日,GNU Bash已经给出最新的升级补丁,大家针对不同的版本尽快进行升级。升级补丁:
2. 名称解释:
CVE:通用漏洞披露(Common Vulnerabilities and Exposures)
Vulnerabilities:n.缺陷(vulnerability的复数形式);脆弱点
Exposures:暴露, 揭露
Shellshock: 国内中文名为”破壳”
Shock: n. 休克;震惊, vt. 使休克;使震惊;
二. 攻击者如何利用Bash漏洞发起攻击
1) Bash漏洞是由于bash解释器对变量,函数的定义,过滤不严格导致的,而攻击者利用这个漏洞进行代码注入。
2) 攻击者可以向目标系统发起特意修改的HTTP请求,该请求中某些字段通过影响环境变量可以将恶意代码注入到服务器中,当服务器fork新进程时,会将环境变量引入新的子进程中执行恶意代码,如: HTTP_USER_AGENT这样的环境变量,只由浏览器发出的。
3) 如果系统中存在了攻击者植入的环境变量,当系统执行新的程序时,会引入环境变量,而其中混入恶意代码将被执行
三. Babsh漏洞的检测
1. 环境说明:
统版本:CentOS release 6.5 (Final)
内核版本: 2.6.32-431.el6.x86_64
Bash版本: GNU bash, version 4.1.2(1)-release (x86_64)
2. 漏洞验证: CVE-2014-6271:
[root@master ~]# env x='() { :;}; echo CVE-2014-6271 ' bash -c "echo test"
如果出现如下两行,则说明bash存在6271漏洞。
CVE-2014-6271
test
3. 漏洞验证:CVE-2014-7169
[root@master ~]# env x='() { (a)=>\' bash -c "echo date"; cat echo
如果出现如下提示:则说明bash存在7169漏洞。
bash: x: line 1: syntax error near unexpected token `='
bash: x: line 1: `'
bash: error importing function definition for `x'
Sun Apr 19 22:03:03 CST 2015 此处是当前系统时间
四. Bash漏洞的修复
a) YUM方式:
yum clean all
yum makecache
yum -y update bash
b) 源码方式:
2. 登录
3. 下载新版本bash源码包,然后上传到目标系统
下载 07-Nov-2014 09:19 7.6M
注意最后修改日期: 2014-11-07(因漏洞发现于2014-09-25)
所以,BASH版本要下载漏洞发现日期之后的bash包
下载后,上传到目标系统之止
或者直接从目标系统里下载
Wget
4. YUM安装编辑工具: gcc gcc-c++ automake autoconf
yum install gcc gcc-c++ automake autoconf –y
Installing: |
autoconf noarch 2.63-5.1.el6 c6-media 781 k |
automake noarch 1.11.1-4.el6 c6-media 550 k |
gcc x86_64 4.4.7-4.el6 c6-media 10 M |
gcc-c++ x86_64 4.4.7-4.el6 c6-media 4.7 M |
Installing for dependencies: |
cloog-ppl x86_64 0.15.7-1.2.el6 c6-media 93 k |
cpp x86_64 4.4.7-4.el6 c6-media 3.7 M |
libstdc++-devel x86_64 4.4.7-4.el6 c6-media 1.6 M |
mpfr x86_64 2.4.1-6.el6 c6-media 157 k |
ppl x86_64 0.10.2-11.el6 c6-media 1.3 M |
5. 安装bash-4.3.30
tar –zxf bash-4.3.30.tar.gz
cd /root/bash-4.3.30
./configure 默认安装于/usr/local
make && make tests && make install
过程稍有点长,请耐心等待。。。。。。
等安装完成后, 重启系统reboot
6. Bash新版本的查看
[root@master ~]# bash --version
GNU bash, version 4.3.30(1)-release
7. 另一版本的安装:bash-4.2.53.tar.gz
过程与安装bash-4.3.30方法相同
唯一的区别: 比刚才第3步多安装一个包
五. Bash漏洞的修复验证
1. 漏洞修修复验证:CVE-2014-6271:
[root@master ~]# env x='() { :;}; echo CVE-2014-6271 ' bash -c "echo test"
test
如果只输出test, 表示漏洞已经修复
2. 漏洞修复验证:CVE-2014-7169:
[root@master ~]# env x='() { (a)=>\' bash -c "echo date"; cat echo
date
cat: echo: No such file or directory
如果输出如上两行,表示漏洞已经修复
六. Bash漏洞的分析
以下内容引自:《 bash代码注入的安全漏洞原理详解》
说得太详细了,原理和细节这部分就直接引用了。
原理和技术细节
要说清楚这个原理和细节,我们需要从 bash的环境变量开始说起。
bash的环境变量
环境变量大家知道吧,这个不用我普及了吧。环境变量是操作系统运行shell中的变量,很多程序会通过环境变量改变自己的执行行为。在bash中要定义一个环境变量的语法很简单(注:=号的前后不能有空格):
1 |
$ var="hello world" |
然后你就可以使用这个变量了,比如:echo $var什么的。但是,我们要知道,这个变量只是一个当前shell的“局部变量”,只在当前的shell进程中可以访问,这个shell进程fork出来的进程是访问不到的。
你可以做这样的测试:
1 2 3 4 5 |
$ var="hello coolshell" $ echo $var hello coolshell $ bash $ echo $var |
上面的测试中,第三个命令执行了一个bash,也就是开了一个bash的子进程,你就会发现var不能访问了。
为了要让shell的子进程可以访问,我们需要export一下:
1 |
$ export var="hello coolshell" |
这样,这个环境变量就会在其子进程中可见了。
如果你要查看一下有哪些环境变量可以在子进程中可见(也就是是否被export了),你可使用env命令。不过,env命令也可以用来定义export的环境变量。如下所示:
1 |
$ env $var="hello haoel" |
有了这些基础知识还不够,我们还要知道一个基础知识——shell的函数。
bash的函数
在bash下定义一个函数很简单,如下所示:
1 2 3 |
$ foo(){ echo "hello coolshell"; } $ foo hello coolshell |
有了上面的环境变量的基础知识后,你一定会想试试这个函数是否可以在子进程中调用,答案当然是不行的。
1 2 3 4 5 6 |
$ foo(){ echo "hello coolshell"; } $ foo hello coolshell $ bash $ foo bash: foo: command not found |
你看,和环境变量是一样的,如果要在子进程中可以访问的话,那么,还是一样的,需要export,export有个参数 -f,意思是export一个函数。如:
1 2 3 4 5 6 7 |
$ foo(){ echo "hello coolshell"; } $ foo hello coolshell $ export -f foo $ bash $ foo hello coolshell |
好了,我讲了这么半天的基础知识,别烦,懂了这些,你才会很容易地理解这两个漏洞是怎么回事。
好,现在要进入正题。
bash的bug
从上面我们可以看到,bash的变量和函数用了一模一样的机制,如果你用env命令看一下export出来的东西,你会看到上面我们定义的变量和函数都在,如下所示(我省略了其它的环境变量):
1 2 3 4 |
$ env var=hello coolshell foo=() { echo "hello coolshell" } |
原来,都用同样的方式啊——无论是函数还是变量都是变量啊。于是,看都不用看bash的源代码,聪明的黑客就能猜得到——bash判断一个环境变量是不是一个函数,就看它的值是否以”()”开始。于是,一股邪念涌上心头。
黑客定义了这样的环境变量(注:() 和 { 间的空格不能少):
1 |
$ export X='() { echo "inside X"; }; echo "outside X";' |
env一下,你会看到X已经在了:
1 2 |
$ env X=(){ echo "inside X"; }; echo "outside X"; |
然后,当我们在当前的bash shell进程下产生一个bash的子进程时,新的子进程会读取父进程的所有export的环境变量,并复制到自己的进程空间中,很明显,上面的X变量的函数的后面还注入了一条命令:echo “outside X”,这会在父进程向子进程复制的过程中被执行吗?(关于fork相关的东西你可以看一下我以前写的《》)
答案是肯定的。
1 2 3 |
$ export X='() { echo "inside X"; }; echo "outside X";' $ bash outside X |
你看,一个代码注入就这样完成了。这就是bash的bug—— 函数体外面的代码被默认地执行了。
我们并不一定非要像上面那样创建另一个bash的子进程,我们可以使用bash -c的参数来执行一个bash子进程命令。就像这个安全漏洞的测试脚本一样:
1 |
env VAR='() { :;}; echo Bash is vulnerable!' bash -c "echo Bash Test" |
其中,() { :;} 中的冒号就相当于/bin/true,返回true并退出。而bash -c其实就是在spawn一个bash的echo的子进程,用于触发函数体外的echo命令。所以,更为友好一点的测试脚本应该是:
1 |
env VAR='() { :;}; echo Bash is vulnerable!' bash -c "echo 如果你看到了vulnerable字样说明你的bash有安全问题" |
OK,你应该明白这个漏洞是怎么一回事了吧。
bash漏洞的影响有多大
在网上看到好多人说这个漏洞不大,还说这个事只有那些陈旧的执行CGI脚本的网站才会有,现在已经没有网站用CGI了。我靠,这真是无知者无畏啊。
我举个例子,如果你的网站中有调用操作系统的命令,比如你用PHP执行个exec之类的东西。这样的需求是有的,特别是对于一些需要和操作系统交互的重要的后台用于管理的程序。于是就会开一个bash的进程来执行。
我们还知道,现在的HTTP服务器基本上都是以子进程式的,所以,其中必然会存在export 一些环境变量的事,而有的环境变量的值是从用户端来的,比如:HTTP_USER_AGENT这样的环境变量,只由浏览器发出的。其实这个变量你想写成什么就写成什么。
于是,我可以把这个HTTP_USER_AGENT的环境变量设置成上述的测试脚本,只不过,我会把echo Bash is vulnerable!这个东西换成别的更为凶残的命令。呵呵。
关于 AfterShock – CVE-2014-7169 测试脚本的解释
很多同学没有看懂下面这个测试脚本是什么意思,我这里解释一下。
1 |
env X='() { (a)=>\' sh -c "echo date"; cat echo |
· X='() { (a)=>\’ 这个不用说了,定义一个X的环境变量。但是,这个函数不完整啊,是的,这是故意的。另外你一定要注意,\’不是为了单引号的转义,X这个变量的值就是 () { (a)=>\
· 其中的 (a)=这个东西目的就是为了让bash的解释器出错(语法错误)。
· 语法出错后,在缓冲区中就会只剩下了 “>\”这两个字符。【不明白为何只剩下>\】
· 于是,这个神奇的bash会把后面的命令echo date换个行放到这个缓冲区中,然后执行。
相当于在shell 下执行了下面这个命令:
1 2 |
$ >\ echo date |
如果你了解bash,你会知道 \ 是用于命令行上换行的,于是相当于执行了:
1 |
$ >echo date |
这不就是一个重定向么?上述的命令相当于:
1 |
$ date > echo |
于是,你的当前目录下会出现一个echo的文件,这个文件的内容就是date命令的输出。
重点部分再说明一下:
[root@master ~]# > testfile date
#上面这行的意思是 date命令的执行结果 重定向到 testfile中
[root@master ~]# cat testfile
Tue Apr 14 08:22:38 CST 2015
> testfile date 等价于 date > testfile
[root@master ~]# >\ > 在这里是重定向符号
> testfile date
[root@master ~]#
测试语句再说明一下:
env X='() { (a)=>\' sh -c "echo date"; cat echo |
蓝色的date是执行的命令,攻击者可以将其换成恶意代码
红色的echo在这里不是echo命令,而是date执行结果要输出的文件
>\ 是重定向符号与 连续符号