章节大纲

  • 由于 system() 会调用 shell 程序,在 Set-UID 程序中调用 system() 是非常危险的。这是因为 shell 程序的行为可能受到环境变量(如 PATH)的影响。这些环境变量是由用户提供的,而用户是不可信的。通过更改这些变量,恶意用户可以控制 Set-UID 程序的行为。在 Bash 中,你可以通过以下方式更改 PATH 环境变量(此示例将目录 /home/seed 添加到 PATH 环境变量的开头):

    $ export PATH=/home/seed:$PATH

    下面的 Set-UID 程序应该执行 /bin/ls 命令,然而,程序员只使用了相对路径来执行 ls 命令,而不是绝对路径:

    int main()
    {
      system("ls");
      return 0;
    }

    请编译上述程序,将其所有者改为 root,并将其设置为 Set-UID 程序。你能否让这个 Set-UID 程序运行你自己的恶意代码,而不是 /bin/ls?如果可以,你的恶意代码是否以 root 权限运行? 描述并解释你的观察结果。

    注意:

    system(cmd) 函数会首先执行 /bin/sh 程序,然后让该 shell 程序运行 cmd 命令。在 Ubuntu 20.04(以及之前的几个版本)中,/bin/sh 实际上是一个指向 /bin/dash 的符号链接。该 shell 程序有一种防范措施,可以防止自己在 setuid 进程中被执行。如果 dash 检测到它在 Set-UID 进程中执行,它会立即将有效用户 ID 更改为进程的真实用户 ID,从而放弃特权。

    由于我们的受害程序是一个 Set-UID 程序,/bin/dash 中的对策可以阻止我们的攻击。 为了查看没有这种对策的情况下攻击的效果,我们将 /bin/sh 链接到另一个没有此防范措施的 shell,我们已在 Ubuntu 20.04 虚拟机中安装了一个这样的名为 zsh 的 shell 程序。我们使用以下命令将 /bin/sh 链接到 /bin/zsh:

    $ sudo ln -sf /bin/zsh /bin/sh