通过使用环境变量来利用SUID程序

通过使用环境变量来利用SUID程序

假设我有一个属于用户 Bob 的易受攻击的 SUID 程序,所有用户都可以执行该程序。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
  const char* s = getenv("USER"); // for debugging
  printf("%s\n", s); // for debugging

  char cmd[256] = "/home/bob/hello.sh $USER"; //hello.sh prints "Hello world"
  execl("/bin/bash", "bash", "-p", "-c", cmd, NULL);

  return 0;
}

我想利用它运行的命令附加了 USER 环境变量这一事实来读取只有 Bob 可以看到的文件。例如,如果我将 USER 设置为";cat /home/bob/secret-file"

env USER=";cat /home/bob/secret-file" ./program

这不会运行,只会返回:

;cat /home/bob/secret-file
Hello world

尽管 USER 环境变量发生更改,但第二个命令永远不会运行。

在不编辑 C 代码的情况下,如何使用 USER 环境变量运行“cat”等命令,以使用 bob 的权限运行它(因为该程序是 SUID)并查看只有 bob 可以看到的文件。

答案1

你想做的事情是不可能的。这与 C 或 SUID 无关,而与 shell 如何扩展变量有关。

将 shell 的输入解析为单独的 shell 命令扩展环境变量。变量的内容是不是根据 shell 语法进行解释(否则foo='$foo' ; : $foo将是无限循环)。这意味着将变量插入命令行永远不能将其拆分为多个单独的命令行。如果变量未加引号,则仅意味着变量的内容可以在空格上拆分为命令的多个参数。这可能会也可能不会创建某种可利用的漏洞,但它不会是直接 shell 注入。

如果您将hello.sh脚本替换为:

#!/bin/sh
i=1
for arg in "$@"; do
    echo "argument #$i: [[$arg]]"
    i="$(expr "$i" + 1)"
done

您会注意到它是通过第一个参数;cat和第二个参数调用的/home/bob/secret-file。 shell 不会将 解释;为命令分隔符,它只是传递它。

相关内容