Bash是Linux用户经常采用的一种用于操作命令行界面的软件,这个新近发现的bash安全缺陷被称为Bash bug或Shellshock。用户在正常使用期间,只要shell保持活跃,这个缺陷就使得攻击者能够运行任意指令代码,这简直为各类网络入侵行为提供了便利条件!情况更加糟糕,这个缺陷在企业用软件中潜伏了很久,这种状况让人联想到“心脏出血”,它同样存在了很长时间,这简直让软件公司头疼不已,修复每一个缺陷的实例,谈何容易,实际操作起来困难重重!幸运的是红帽公司与Fedora已经发布了安全更新,不过谷歌安全研究员Tavis Ormandy在社交平台上指出,由Linux系统服务商提供的补丁好像“不够全面”,这引起了众多安全工作者的某种忧虑
该漏洞相关报道:
这个网址指向的是freebuf新闻的一个具体文章页面,内容编号为44805,属于该网站发布的信息之一。
该网站提供了关于bash远程漏洞利用的信息,涉及CVE-2014-6271,内容详尽,值得参考。
测试
在Bash Shell下执行以下代码:
设置环境变量x,其值为空括号内无内容,随后执行一个空操作,接着输出易受攻击,然后执行bash命令,并打印出这是一条测试信息
如果输出:
vulnerable
this is a test
表示存在漏洞。打了补丁会输出以下错误:
bash发出提醒:对于x,将忽略函数定义的尝试
bash: `x' 函数定义导入错误
this is a test
原理分析
在Shell中能够设定变量,在实验中设定了一个名称为x的变量,里面存储了一段文本内容
() { :;}; echo vulnerable
而根据漏洞情报了解,该漏洞源于Shell在解析函数定义时,运行了函数体后续的指令。但其中x的值是文本类型,它是如何变成函数的。
这个情况跟Bash功能相关,在Bash环境下创建一个功能,其规格如下:
function function_name() {
body;
}
当Bash启动并设置环境变量期间,如果语法分析程序遇到圆括号和花括号,就会判定这是一个函数声明。
把say_hello变量赋值为一个匿名函数,这个函数不接受任何参数,当被调用时会输出hello world这个字符串 设置环境变量名为say_hello, 将其值指定为默认问候语, 这个操作可以在当前bash会话中生效, 新建进程不会继承该变量 执行名为say_hello的bash命令,在终端界面显示问候语 hello world
那个脚本在新启动的Bash进程中,say_hello变成了当前环境里一个可用的函数,它的变化步骤是这样的:
新bash启动时,检测到环境变量say_hello包含括号和花括号,判定其为函数声明

2、bash把say_hello作为函数名,其值作为函数体
typeset指令能够展示当前环境里所有变量与函数的设定,我们借助typeset来探究这个字符串如何转化为函数。接下来,我们继续之前定义的say_hello函数:
执行特定命令后,列出相关输出内容,并筛选指定范围内的信息,具体包括显示名称为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假如指令等于全局指令
219{
220struct fd_bitmap *bitmap;
它能够分辨指令是否为全局定义的,在新的bash进程开启时,say_hello不仅被识别为函数,还成为了全局性的
在终端界面输入指令,执行bash命令,调用了typeset功能,并指定了-f参数来显示所有已定义的函数名称
say_hello ()
{
echo hello world
}
declare -fx say_hello
声明指令是Bash自带的,用于设定变量的特性,-f标志表明say_hello是一个函数,-x选项意味着say_hello被公开为一个环境变量,因此该指令的作用是使say_hello变为全程可用的函数。
Bash在启动时会设置初始环境变量,并定义一些函数,其初始设置方法是将变量名等于值这样的赋值语句通过eval执行一次,若遇到函数定义,则将其转化为函数,除此之外,Bash不打算做其他事情,但它在解析函数定义时,不小心执行了函数后面的命令,这并非eval的问题,而是语法解析时考虑不够严谨,因此补丁添加了判断函数体是否合法的语句
当标志位包含函数定义标记,并且指令的类型不是函数定义类型时
补充
此外,有人不解POC中{ :; }这段里的冒号与分号,分号充当终止符,而冒号则形同虚设,好比Python里的pass语句,须查阅Bash的正式资料方能明了。
源自:http://blog.knownsec.com/2014/09/bash_3-0-4-3-order-execution-exploration/