/dev/fd 如何使在 sudo 下运行 shell 脚本安全?

kjo*_*kjo 6 security root setuid sudo shell-script

在手册页的末尾sudo,有以下注释:

   Running shell scripts via sudo can expose the same kernel bugs that
   make setuid shell scripts unsafe on some operating systems (if your OS
   has a /dev/fd/ directory, setuid shell scripts are generally safe).
Run Code Online (Sandbox Code Playgroud)

那段中的几乎所有内容对我来说都是模糊的。特别是,我想了解典故/dev/fd的全部内容。我试图猜测一些可能的手册页,我可以在其中找到这些信息,但我发现是空的。

有什么建议?

(如果可能的话,最终我想通过 cron 在 sudo 下运行一些脚本,但当然我担心这种无人监督的安排中可能存在安全漏洞。)

Sté*_*las 6

我看不出这如何适用于sudo.

对于 setuid 脚本,想法是这样的:

假设您有一个/usr/local/bin/myscriptsetuid root 并以#! /bin/sh. 没有人对/usr/local/binor有写权限myscript,但任何人都可以:

ln -s /usr/local/bin/myscript /tmp/-i
Run Code Online (Sandbox Code Playgroud)

并且/tmp/-i也变成了一个 setuid 脚本,即使您仍然没有对它的写访问权限,但您确实有对/tmp.

在不通过 执行 setuid 脚本的系统上/dev/fd,当您执行时cd /tmp && -i, setuid 位意味着它将/bin/sh -i以 root 身份运行:

  1. 该过程将 euid 更改为文件所有者
  2. 系统解析shebang
  3. 系统执行(仍为 root), /bin/sh -i

现在,对于这种特殊情况,简单的解决方法是按照推荐的方式编写 shebang: #! /bin/sh -,但即便如此,也存在竞争条件。现在变成了:

  1. 该过程将 euid 更改为文件所有者
  2. 系统解析shebang
  3. 系统执行(仍为 root), /bin/sh - -i
  4. “sh”打开当前目录中的“-i”文件(你会认为很好)。

但是在上面的 3 和 4 之间,您有足够的时间将“-i”或(“any-file”,因为这里是不同的攻击向量)更改为一些邪恶的“-i”文件,例如仅包含“sh”你会得到一个 root shell(用于 setuid root 脚本)。

对于旧版本的ksh,您甚至不需要这样做,因为在 4 中,ksh 首先在 中查找“-i” $PATH,因此将邪恶的“-i”放入$PATHksh会打开那个而不是那个在/tmp)。

如果您执行以下操作cd /tmp; -i,则所有这些攻击向量都是固定的:,系统改为执行以下操作(仍在 execve 系统调用中):

  1. 原子地:找出文件是 setuid 并x在进程的某个文件描述符上打开文件。
  2. 处理对文件所有者的 euid 更改。
  3. /bin/sh /dev/fd/x
  4. shopens/dev/fd/x只能引用execved的文件。

关键是该文件是作为 execve 的一部分打开的,因此我们知道它将使用更改的权限来解释具有可信内容的代码。

现在这不适用于,sudo因为该sudo政策基于path.

如果sudo规则说您可以以 root 身份运行 /usr/local/bin/myscript,那么您可以执行以下操作:

sudo /usr/local/bin/myscript
Run Code Online (Sandbox Code Playgroud)

但你不能这样做:

sudo /tmp/any-file
Run Code Online (Sandbox Code Playgroud)

即使“任何文件”是指向/usr/local/bin/myscript. sudo 不使用/dev/fdAFAICT。