
Shellshock
Shellshock
请下载 docker-compose.yml 和 poc.py 文件 务必通过 pip install requests 安装 requests 库!!! 使用 uv 的用户请通过 uv 将 requests 库放入 venv 中!!!
| CVE 官方描述 |
|---|
| GNU Bash 4.3 之前版本在环境变量值中处理函数定义后跟的字符串时存在问题。利用此漏洞,远程攻击者可以通过精心构造的环境执行任意代码。该漏洞在 OpenSSH sshd 的 ForceCommand 功能、Apache HTTP 服务器的 mod_cgi 和 mod_cgid 模块、未指定 DHCP 客户端中执行的脚本,以及 Bash 执行权限与环境变量设置跨越不同权限边界的多种情况下被发现。此漏洞也被称为 "ShellShock"。注意:该问题的初始修复存在错误,在错误修复后仍存在的此漏洞由 CVE-2014-7169 解决。 |

| 环境配置 |
|---|
Docker 文件配置
| 操作系统 | Web 服务器 | Bash 版本 |
|---|---|---|
| Debian 10 | Apache | 4.2.37(1) |

为了在执行 docker compose up 命令后保持 Web 服务器运行状态,编写了 Dockerfile。
由于 Dockerfile 中的操作系统、Apache 等都是从外部仓库下载的,因此将构建好的镜像打上标签推送到 Docker Hub,然后在 docker-compose.yml 文件中指定该镜像,这样即使原始文件被删除也能保证正常运行。

| 漏洞条件 |
|---|
需要存在 Shellshock 漏洞的 Bash shell。我下载并使用了 4.2.37(1) 版本的 Bash shell。

此外,需要将代码注册到环境变量后调用 Bash 才能使代码执行,因此需要存在能够调用 Bash 的程序。 我下载了 CGI 程序,用于 Web 服务器处理客户端请求。 CGI 规范(RFC 3875)规定 Web 服务器将浏览器发送的所有头部信息放入 Linux 环境变量中进行处理。
在此条件下,Web 服务器发送请求,其头部信息根据 CGI 规范存储到环境变量中。 通过 CGI 调用存在漏洞的 Bash shell(该 shell 会在环境变量中函数定义后执行字符串),从而完成攻击。
请求(将代码嵌入 User-Agent 头部发送) -> CGI 调用 Bash -> 反向 shell 连接
| 复现步骤 |
|---|

| 实现结果 |
|---|
在复现步骤 2 中监听的终端将连接到容器内部的 Bash shell,可以执行 whoami、id 等命令。

| 漏洞成因 |
|---|
'''
if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
{
string_length = strlen (string);
temp_string = (char *)xmalloc (3 + string_length + char_index);
strcpy (temp_string, name);
temp_string[char_index] = ' ';
strcpy (temp_string + char_index + 1, string);
parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
// 以下省略
'''
漏洞原因在于 Bash shell 代码中 variables.c 文件内的 initialize_shell_variables 函数。 该函数本身也很长,这里只截取了核心部分。
'''
if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
'''
上述 if 语句通过 STREQN ("() {", string, 4) 检查字符串的前四个字符是否为 "() {"。 如果匹配,就会将其视为函数。 令人惊讶的是,此后没有对 string 进行任何过滤,因此导致了问题。
'''
strcpy (temp_string, name);
temp_string[char_index] = ' ';
strcpy (temp_string + char_index + 1, string);
''' 上述代码是将名称和值合并的过程。由于已经经过上面的检查,string 是以 "() {" 开头的形式, 而 name 是环境变量的名称。
这样,将环境变量的名称和值组合后传递给下面的代码进行解析。 因为过滤只检查了开头的 "() {",所以在函数后面附加 whoami、id、pwd 等命令也会全部执行。
'''
parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
'''
| 应对措施 |
|---|
| 升级 Bash 版本到不受 Shellshock 漏洞影响的版本。 |
| 不要使用调用 Bash shell 的程序。 |