漏洞简介
GNU Bash 4.3及之前版本在评估某些构造的环境变量时存在安全漏洞,向环境变量值内的函数定义后添加多余的字符串会触发此漏洞,攻击者可利用此漏洞改变或绕过环境限制,以执行Shell命令。某些服务和应用允许未经身份验证的远程攻击者提供环境变量以利用此漏洞。此漏洞源于在调用Bash Shell之前可以用构造的值创建环境变量。这些变量可以包含代码,在Shell被调用后会被立即执行。 破壳漏洞的严重性被定义为10级(最高),今年4月爆发的OpenSSL“心脏出血”漏洞才5级!
为什么这个漏洞如此受关注?
1、影响范围广,漏洞存在时间长。
Bash,Unix shell的一种。1989年发布第一个正式版本,原先是计划用在GNU操作系统上,但能运行于大多数类Unix系统的操作系统之上,包括Linux与Mac OS X v10.4都将它作为默认shell。它也被移植到Microsoft Windows上的Cygwin与MinGW,或是可以在MS-DOS上使用的DJGPP项目。在Novell NetWare与Android上也有移植。
所以这个漏洞存在于目前主流的Linux和MacOSX操作系统。该漏洞会影响到与bash交互的各种应用程序,如HTTP,FTP,DHCP等等。
出问题的bash代码已经存在20多年了。
漏洞原理
要理解这个漏洞首先要知道什么是bash环境变量,下面引用左耳朵耗子的文章
环境变量大家知道吧,这个不用我普及了吧。环境变量是操作系统运行shell中的变量,很多程序会通过环境变量改变自己的执行行为。在bash中要定义一个环境变量的语法很简单(注:=号的前后不能有空格):
1 | $ var= |
然后你就可以使用这个变量了,比如:echo $var什么的。但是,我们要知道,这个变量只是一个当前shell的“局部变量”,只在当前的shell进程中可以访问,这个shell进程fork出来的进程是访问不到的。
你可以做这样的测试:
1 2 3 4 5 | $ var= |
上面的测试中,第三个命令执行了一个bash,也就是开了一个bash的子进程,你就会发现var不能访问了。
为了要让shell的子进程可以访问,我们需要export一下:
1 | $ |
这样,这个环境变量就会在其子进程中可见了。
如果你要查看一下有哪些环境变量可以在子进程中可见(也就是是否被export了),你可使用env命令。不过,env命令也可以用来定义export的环境变量。如下所示:
1 | $ |
有了这些基础知识还不够,我们还要知道一个基础知识——shell的函数。
bash的函数
在bash下定义一个函数很简单,如下所示:
1 2 3 | $ foo(){ |
有了上面的环境变量的基础知识后,你一定会想试试这个函数是否可以在子进程中调用,答案当然是不行的。
1 2 3 4 5 6 | $ foo(){ |
你看,和环境变量是一样的,如果要在子进程中可以访问的话,那么,还是一样的,需要export,export有个参数 -f,意思是export一个函数。如:
1 2 3 4 5 6 7 | $ foo(){ |
Bash 漏洞的测试代码
在Bash Shell下执行以下代码:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
如果输出:
vulnerable
this is a test
表示存在漏洞。打了补丁会输出以下错误:
bash: 警告: x: ignoring function definition attempt
bash: `x' 函数定义导入错误
this is a test
原理分析
Shell里可以定义变量,POC中定义了一个命名为x的变量,内容是一个字符串:
() { :;}; echo vulnerable
而根据漏洞信息得知,这个漏洞产生于Shell在处理函数定义时,执行了函数体之后的命令。但这里x的值是个字符串,它是怎么转变成函数的呢。
实际这个和Bash实现有关,在Bash中定义一个函数,格式为:
function function_name() {
body;
}
当Bash在初始化环境变量时,语法解析器发现小括号和大括号的时候,就认为它是一个函数定义:
[lu4nx@lx-pc ~]$ say_hello='() { echo hello world; }'
[lu4nx@lx-pc ~]$ export say_hello
[lu4nx@lx-pc ~]$ bash -c 'say_hello'
hello world
上面代码在新的Bash进程中,say_hello成了新环境中的一个函数,它的演变过程如下:
1、新的bash在初始时,扫描到环境变量say_hello出现小括号和大括号,认定它是一个函数定义
2、bash把say_hello作为函数名,其值作为函数体
typeset命令可以列出当前环境中所有变量和函数定义,我们用typeset看看这个字符串怎么变成函数的。继续上面定义的say_hello函数:
[lu4nx@lx-pc ~]$ bash -c 'typeset' | fgrep -A 10 say_hello
say_hello ()
{
echo hello world
}
这里新启动了个Bash进程,然后执行了typeset,typeset会返回当前环境(新的环境)中所有定义,这里清楚看到say_hello被变成函数了。
漏洞产生原因
而这个漏洞在于,Bash把函数体解析完了之后,去执行了函数定义后面的语句,为啥会这样呢。
通过结合补丁,我对Bash的源码简单分析了下,Bash初始化时调用了builtins/evalstring.c里的parse_and_execute函数。是的,就等于Bash初始化环境时调用了类似其他高级语言中的eval函数,它负责解析字符串输入并执行。
继续看parse_and_execute的源码,关键点在这里:
218 else if (command = global_command)
219 {
220 struct fd_bitmap *bitmap;
它判断命令是否是一个定义成全局的,新的bash进程启动后,say_hello不仅被解析成函数了,还变成全局的了:
[lu4nx@lx-pc data]$ bash -c 'typeset -f'
say_hello ()
{
echo hello world
}
declare -fx say_hello
declare命令是Bash内置的,用来限定变量的属性,-f表示say_hello是一个函数,-x参数表示say_hello被export成一个环境变量,所以这句话的意思是让say_hello成了全局有效的函数。
其实Bash本身其实是想在启动时初始环境变量以及定义一些函数,而初始的方式就是去把 变量名=值 这样的赋值语句用eval去执行一次,如果出现了函数定义,就把它转变成函数,除此之外就不想让它干其他的了,可偏偏它在扫描到函数定义时,把它转变成函数的过程中不小心执行了后面的命令,这其实不是eval的错,这是做语法解析时没考虑严格,所以补丁加了这么一句话来判断函数体合法性:
if ((flags & SEVAL_FUNCDEF) && command->type != cm_function_def)
上面的官方补丁打了补丁之后,随后被绕过
执行下面命令:
1 | env |
上面这段代码运行起来会报错,但是它要的就是报错,报错后会在你在当前目录下生成一个echo的文件,这个文件的内容是一个时间文本。下面是上面 这段命令执行出来的样子。
1 2 3 4 5 | $ |
原理分析:
官方提供的第一个补丁主要修改了:
1、参数类型和个数的限制,从注释中即可看出:
#define SEVAL_FUNCDEF 0x080 /* only allow function definitions */ #define SEVAL_ONECMD 0x100 /* only allow a single command */
2、给builtins/evalstring.c文件里的parse_and_execute加入了类型判断:
if ((flags & SEVAL_FUNCDEF) && command->type != cm_function_def)
{
不合法,不是函数定义
break;
}
...
// 逻辑为真就表明参数不合法
if (flags & SEVAL_ONECMD)
break;
从上面即可看出补丁思路:如果不是函数定义、命令(command)超过一个就判为不合法。什么才算合法呢,Bypass POC给出了答案:
env X='() { (x)=>\' ./bash -c 'my echo hello'
只要函数体满足() {打头就行了。并且这条POC也满足单个命令(command),因为没出现“;”。
Bash Shell在eval的时候遇到语法问题(x)=被忽略了。语法出错后,在缓冲区中就会只剩下了 “>\”这两个字符
接着就来到重点了,新的bash进程执行了这条命令:
$>\
my echo hello
如果你了解bash,你会知道 \ 是用于命令行上换行的,于是相当于执行了
$>\my echo hello
然后在路径下生成了my文件,内容为hello。
Bash语法极其怪异,让我们逐一分析。
字符\是个转移字符,会保留后面跟的文本,\my实际等于字符串my,如果没有\,新的bash进程会把my当作是命令。因为如果你在终端只输入\并回车,当前bash进程会阻塞等待你输入,在POC里,“输入”的就是my。
字符>就是传说中的重定向,假设要把进程A的输出写入到文件B中,就写成如下:
A > B
其实你写成> B A形式也可以,不信试试:
[lu4nx@lx-pc /tmp]$ > hi date
[lu4nx@lx-pc /tmp]$ cat hi
2014年 09月 27日 星期六 01:06:06 CST
这种前缀写法我也是头一次见到,这次分析Shell源码,看得出它的设计极其像一个Lisp解析器,我以为这种写法是照顾Lisper,因为 Bash结构基本上就是一个交互式(REPL)和eval,而Lisp解析器的核心就是eval,直到我看了Shell的Yacc语法分析 (parse.y)后,我才恍然大悟。重定向的语法定义如下:
redirection: '>' WORD
{
redir.filename = $2;
$$ = make_redirection (1, r_output_direction, redir);
}
这里表示,输出的文件是取自$2,$2在这段表示参数WORD,如果输入的语句是> A B,那么WORD的实参就是A;如果输入的语句是A > B,那么WORD的实参就是B。
所以POC的思路就是定义一个语法不合法的函数体,绕过函数定义的检测代码,然后执行了后面的命令,最终让Bash在初始化的时候执行了>\my echo hello。
------------------------------------------------------------------------------==============================
Shellshock漏洞的工作原理是:攻击者可以向任何使用bash交互的系统如Web服务器、Git版本控制系统和DHCP客 户端发送请求,请求包含了以环境变量储存的数据。环境变量就像是操作系统的剪切板,储存了帮助系统和软件运行的信息。在本案例中,攻击者发送的请求是精心构造的,诱骗bash将其视为命令,bash像平常执行良性脚本那样执行命令。这种欺骗bash的能力就是Shellshock漏洞。官方发布的补丁被发 现仍然存在相似的漏洞。
计算机科学家David A. Wheeler在 邮件列表上指出,bash的解析器存在许多漏洞,因为它在设计时就没有考虑过安全性,除非它停止解析环境变量,否则修正就像是打地鼠。Wheeler建议 打上非官方的补丁修正bash,这些补丁会破坏向后兼容性。其中一个补丁来自德国计算机安全专家Florian Weimer,他的补丁为bash函数加入前缀,防止它们被指明为系统变量。另一个补丁来自NetBSD开发者Christos Zoulas博士,他的补丁只允许bash在收到明确请求时输入环境变量,消除安全风险。
FreeBSD的bash实现则在最新的修正中默认关闭了通过环境变量引入函数的功能。Wheeler等人相信,虽然破坏了向后兼容性,但不会影响太多的bash依赖系统。
苹果的OS X系统也存在Shellshock漏洞, 苹果表示大部分用户不会面临风险,只有配置了advanced UNIX services的用户会受到影响。OS X使用了v3.2.51.(1)的GNU bash,由于新版本bash许可证换到了条款更严格的GPLv3,所以苹果仍然使用旧版本.
参考改编文章
http://coolshell.cn/
http://blog.knownsec.com/2014/09/bash_3-0-4-3-command-exec-analysis/
http://blog.knownsec.com/2014/09/bash_3-0-4-3-command-exec-patch-bypass-analysis/
http://www.antiy.com/response/CVE-2014-6271.html
http://blog.csdn.net/smstong/article/details/39579767
http://www.linuxidc.com/Linux/2014-10/108239p2.htm
http://linux.cn/article-3918-1.html
所有的补丁都打好后,本机系统ubuntu12.04LTS,写此篇博客时的bash版本为 4.2.25(1)-release (x86_64-pc-linux-gnu)。做了些实验,bash补丁 修复,在修复中默认关闭了通过环境变量引入函数的功能!
相关推荐
在"shellshock漏洞的redhat最新补丁及说明"中,Red Hat企业Linux(RHEL)5和RHEL 6这两个版本受到了直接影响。RHEL 5是Red Hat发布的一款长期支持的操作系统,而RHEL 6则是在其之后的一个主要版本,两者都有32位和64...
破壳漏洞(shellshock)红帽4 X86(32位)补丁 内含: bash-3.0-27.0.3.el4.i386.rpm bash-debuginfo-3.0-27.el4.4.i386.rpm ------------------------------------------- 验证命令: env x='() { :;}; echo vulnerable'...
shellshock 补丁 for rhel5.11 x64
这些Bash漏洞现在都是破壳漏洞集中的,目前所有补丁,截止2014.10.05的官方补丁已经全部修补完成。压缩包内有一个检测脚本,只针对前几个流传广泛的6271、7169、7186等检测,后面几个没有检测。感兴趣的可以试一试。...
从红帽更新服务器上下载下来的,里面包含 RedHat5 X86:bash-3.2-33.el5_11.4.i386.rpm RedHat5 X86_64:bash-3.2-33.el5_11.4.x86_64.rpm bash-debuginfo-3.2-33.el5_11.4.x86_64.rpm RedHat6 X86:bash-4.1.2-15.el6...
shellshock代码,网页形式,看起来不错,需要到可以试试哦。
Shellshock漏洞,全名是BASH(Bourne Again SHell)漏洞,是2014年9月被发现的一个严重安全漏洞,影响了广泛使用的Unix/Linux操作系统及基于这些系统的服务器、路由器、智能家居设备等。这个漏洞源于bash shell的环境...
破壳漏洞(shellshock)红帽4 X86(32位)补丁 内含: bash-3.0-27.0.3.el4.i386.rpm bash-debuginfo-3.0-27.el4.4.i386.rpm ------------------------------------------- 验证命令: env x='() { :;}; echo vulnerable'...
破壳漏洞(shellshock)红帽4 X86(32位)补丁
研究人员周四发布警告称 黑客已经开始利用最新的“Shellshock”电脑漏洞 借助蠕虫病毒扫描有漏洞的系统 然后感染这些 redhat 6 5以上版本32 位64位 升级包
**标题与描述解析** ...总之,“RHEL 5 6 bash补丁”是对一个重大安全威胁的响应,及时的应用这个补丁对于保护Linux环境的稳定性与安全性至关重要。同时,了解漏洞的原理和防范措施,可以更好地维护系统的安全。
【Bash漏洞与Shellshock】 Bash漏洞,又称为Shellshock,是指在2014年发现的一种严重安全漏洞,影响了广泛使用的Bash shell程序。Bash是Unix-like操作系统,包括Linux和Mac OS X的默认命令行解释器。这个漏洞的存在...
【Bash漏洞——Shellshock浅析】 Bash漏洞,又称Shellshock,是指在2014年被发现的一个严重安全漏洞,它影响了广泛使用的Bash shell,这是一个在Unix-like操作系统,包括Linux和Mac OS X中的命令行解释器。这个漏洞...
**bash补丁** 在Linux和Unix-like操作系统中,Bash(Bourne-Again SHell)是默认的命令行解释器,它为用户提供了一个交互式环境来执行命令和脚本。由于其广泛使用,Bash的安全性对于整个系统的安全性至关重要。然而...
破壳漏洞(Shellshock)是2014年发现的一个严重的Linux和Unix系统安全漏洞,影响了广泛使用的Bash shell。Bash是GNU项目的一部分,是Linux和类Unix操作系统中的命令行解释器,用于处理用户输入的命令。这个漏洞允许...
在描述中提到的“另一个Linux漏洞补丁合集”,暗示可能存在之前已知的bash漏洞,比如著名的“Shellshock”漏洞,该漏洞允许攻击者通过精心构造的环境变量值来执行任意代码。这些补丁的目的是修补这些已知的安全漏洞...
CGI脚本ShellShock开发工具。 什么是Shellshock? Shellshock是Bash版本1.0.3-4.3中的关键错误,可以使攻击者执行任意命令。 Bash的漏洞版本错误地执行了遵循存储在环境变量中的函数定义的命令-攻击者可以在将用户...
个人测试: [root@localhost ~]# rpm -Uvh --force bash-3.0-27.0.2.el4.i386.rpm warning: bash-3.0-27.0.2.el4.i386.rpm: V3 DSA signature: NOKEY, key ID b38a8516 Preparing... #############################...
3. **攻击示例与复现**:实验中提供的源码将展示如何构造恶意输入来触发ShellShock漏洞。你可以通过修改环境变量,观察系统行为的变化,理解攻击是如何发生的。 4. **防御措施**:学习如何防御ShellShock攻击至关...
shellshock_enum 这是一个通过 Shellshock 枚举系统信息的 metasploit 模块。 在 $MSF/modules/auxiliary/scanner/http 中安装 ruby 脚本 用法: msf > use auxiliary/scanner/http/shellshock_enum msf ...