shellshock 会产生一个全面的本地权限提升向量吗?

信息安全 炮击 重击 特权升级
2021-09-04 04:58:48

如果setuid脚本从调用者那里获取任意环境变量,除了少数列入黑名单的变量,例如LD_LIBRARY_PATH, ,这是否意味着任何直接或间接setuid运行的脚本#!/bin/bash都是本地权限升级的媒介?

一个好的答案是解释为什么会这样或不是这样。

例如,许多(大多数?)unixalikes 现在不支持setuidshell 脚本(尽管在引入这个 bug/后门时他们这样做了)。但是二进制文件可能会间接调用 shell 脚本,所以除非他们先明确清除环境,否则这不是问题吗?

2个回答

是的!

带有setuid一点和调用(直接或间接)bash通过的二进制文件execvepopen或者system是可用于激活 Shell Shock 错误的工具。

*env如果这些命令在运行(或 shell 脚本)之前不负责清除,bash则这些二进制文件可用于运行bash具有 . 权限的任何命令(例如 )root

popen并且system不要让程序员清理 *env.

这是估算此风险的简单审计初稿:

find /  -perm +4000 \
    -exec /bin/zsh -c "ls -dluT {} ; nm -a {} | egrep '(popen|system|execve)' && strings {} | egrep '/bin/(sh|bash)'" \; 2>/dev/null

这不是风险证明,因为*env可能在外壳前叉之前已经清理过。唯一确定的方法是阅读源代码。

下面是一个高度使用的 Unix 的实际版本的结果:

-rwsr-xr-x  1 root  wheel  910848 Sep 29 16:31:18 2014 /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/MacOS/ARDAgent
             U _popen
/bin/bash

(这里最后一次使用的不是攻击证明,而是我自己之前的“审核草案”。)

bash在 setuid(或 setgid)上下文中调用时,即当有效 uid 与真实 uid 不同时,则bash删除权限(将有效 uid 设置回真实 uid)。

例外情况是使用-por -o privilegedSHELLOPTS变量被忽略,所以privileged也在那里)或调用 as 时sh

但是,在这种情况下,函数不会从环境中导入(出于同样明显的原因,类似BASH_ENV, BASH_OPTS,之类的东西也不会导入)。SHELLOPTS

如果是这样,您将不需要 shellshock 漏洞来利用它。只需导出一个echo函数(或脚本调用的任何内容,包括类似的路径/bin/mount)就可以了。

一些 setuid 命令可能会选择将 ruid 设置为 euid。如果他们这样做并且不清理环境并调用 bash(或任何其他 shell),那么游戏就结束了,无论是否存在 shellshock 漏洞。

libc 的动态链接器负责删除一些影响 libc 或链接器的变量(LD_PRELOAD、LOCPATH、LD_LIBRARY_PATH...),但如果它们调用其他命令(如 shell(或 python、或任何其他可以通过环境变量控制其行为的命令),典型的理智方法是清除除经过清理的白名单之外的所有内容。

此类应用程序的一个典型示例是sudo.

默认情况下(使用该env_reset选项),sudo清除环境,设置一些(如PATH, HOME, SUDO_USER...)并在检查其内容后将一些列入白名单,如TERMor DISPLAY该检查的一部分特别注意内容以().

如果env_reset关闭(由用户/管理员禁用),则sudo仍会将一些影响各种 shell 或其他常用工具(如PS4BASH_ENV...)的变量以及内容以 . 开头的变量列入黑名单()

所以 shellshock 不能被利用:

DISPLAY='() {(:);}; ouch;}' sudo trusted-bash-script

现在,可能有 setuid 命令设置 ruid 并且不检查以开头()和调用bash(可能是间接)的变量,但同样不需要 shellshock 错误来利用这些。

一个可能的例外是 apache 的suexec. 据我所知,suexec净化环境,但仅根据名称而不是内容将某些变量列入白名单。如果没有CVE-2014-6271,这不会是一个问题,因为这些名字变量一样QUERYSTRINGHTTP_USER_AGENT不太可能匹配命令的名称,所以并不认为有必要阻止变量,其内容与开始"() {",但在实践中表示它已暴露于 CVE-2014-6271。