Bash破壳漏洞CVE-2014-6271复现分析

Bash破壳漏洞CVE-2014-6271复现分析

这算是很早也很经典的一个漏洞了,“破壳”是一个严重漏洞的别名,在Red Hat、CentOS、Ubuntu 、Fedora 、Amazon Linux 、OS X 10.10中均拥有存在破壳漏洞的Bash版本,同时由于Bash在各主流操作系统的广泛应用,此漏洞的影响范围包括但不限于大多数应用Bash的Unix、Linux、Mac OS X,而针对这些操作系统管理下的数据均存在高危威胁。

“破壳”是Bash(GNU Bourne Again Shell)中出现的允许攻击者通过环境变量执行任意命令的漏洞。

利用条件:Bash 版本小于等于4.3或出现以下回显则会证明存在此漏洞

这里我依旧是用的vulhub的漏洞环境,直接进入到容器里面,是用的bash-4.3的版本。

payload: env x='() { :;}; echo shellshocked’ bash –c “echo test”

我们先把这个payload拆开来看。

再执行完整的payload。

再看正常的bash环境下执行payload。

证明了漏洞的存在,再看看bash的基础知识。这是正常情况输出一个字符串。

我们现在可以试试开一个bash子进程来看一下我们能不能得到变量的值。

没有回显,我们不能够读出变量的值是因为我们开启了一个bash子进程,但变量中的值,仍存在父进程中。所以开启一个shell会话时,一些变量已经可以使用了,这些变量成为环境变量。当我们想在子进程中访问$gname变量的话,我们可以使用export命令将该变量设置成环境变量。

那么同理设置一个bash函数再配合环境变量会怎样呢?

正如我们想的那样,在bash子进程中同样执行了我们的x函数读取了/etc/passwd文件。

如何让字符串变成函数并执行呢?

所以触发并利用破壳漏洞的所需要的几点:

  • 被攻击的bash存在漏洞(版本小于等于4.3)
  • 攻击者可以控制环境变量
  • 新的bash进程被打开触发漏洞并执行命令

从上面的分析中可以看出,漏洞的根本原因存在于Bash的ENV命令实现上,因此漏洞本身是不能够直接导致远程代码执行的。如果要达到远程代码执行的目的,必须借助第三方服务程序作为媒介才能够实现,第三方服务程序也必须要满足众多条件才可以充当此媒介的角色。

漏洞原理

该Bash使用的环境变量是通过函数名称来调用的,导致漏洞出问题是以“(){”开头定义的环境变量在命令ENV中解析成函数后,Bash执行并未退出,而是继续解析并执行shell命令。而其核心的原因在于在输入的过滤中没有严格限制边界,也没有做出合法化的参数判断。

这里引用网上经常看到的一张图来说明该漏洞。

那么接下来用vulhub的环境来验证该漏洞具体的利用方式。

这两个文件的内容是相同的,只是使用的bash版本不同。我们在hackbar添加一个user-agent,放上我们的payload构造一个函数去读取passwd。

() { foo; }; echo Content-Type: text/plain; echo; /bin/cat /etc/passwd

同样的payload在正常的bash版本下则失效了。

不过我看了网上的补丁分析。在补丁中主要进行了参数的合法性过滤,补丁程序在/builtins/evalstring.c的parse_and_execute函数中进行了输入的command进行了合法性的边界检测,将代码注入的可能性排除。在排除中主要用到了flags的两次判断和command的一次类型匹配,为了能够flags判断准确,在补丁中预先定义了SEVAL_FUNCDEF、SEVAL_ONECMD两个标识作为判断依据。

漏洞可能会带来的影响:

1.此漏洞可以绕过ForceCommand在sshd中的配置,从而执行任意命令;
2.如果CGI脚本用Bash编写,则使用mod_cgi或mod_cgid的Apache服务器会受到影响;
3.DHCP客户端调用shell脚本来配置系统,可能存在允许任意命令执行;
4.各种daemon和SUID/privileged的程序都可能执行shell脚本,通过用户设置或影响环境变量值,允许任意命令运行。

不过我个人感觉现在cgi已经用的很少了,而且利于场景和条件有些限制。但是从当年爆发这个漏洞时影响确实挺大的,毕竟涉及的版本都挺多的。但是复现漏洞并不只是关注漏洞本身,更多的还是在于这种发现漏洞的思维!

zgao

如果有什么技术上的问题,可以加我的qq 1761321396 一起交流。