如何允许仅使用受限制的参数/环境/上下文运行 suid exe?

如何允许仅使用受限制的参数/环境/上下文运行 suid exe?

我有一个 suid-to-root 可执行文件,用户只能使用某些参数、环境变量设置和上下文设置来运行它。我无法修改该exe。

我将把 exe 封装在无参数脚本中,每个脚本对应一个允许的参数化、环境和上下文设置。问题是如何允许用户运行这些脚本但不以其他方式运行 exe。

我在下面提出的解决方案或更好的替代方案是否存在任何安全问题?

我不知道 polkit 或 sudo 是否可以做到这一点,但如果有人知道的话,我会对如何做到这一点感兴趣。

我有3个解决方案:

  1. 使用挂载命名空间。全局挂载exe nosuid(如果不运行euid=0则立即退出)。创建私有挂载命名空间并重新挂载exe suid。编写一个只有 arg = 包装脚本名称的小型 suid exe,它进入私有命名空间,删除权限并运行脚本。包装器脚本全部保存在专用目录 (/usr/local/bin/safescripts) 中,硬编码到新的小型 suid exe 中。新的 exe 始终仅调用该目录中的脚本,该目录不包含任何其他内容。

  2. 使用目录“vault”。创建父子目录对 /usr/local/lock 和 /usr/local/lock/vault。两者都是 root:root 所有,/usr/local/lock 是 750,/usr/local/lock/vault 是 755。用户无法在没有帮助的情况下进入保管库。但一旦进入保险库,用户就可以获取其中的内容。将原始 suid exe 移至 /usr/local/lock/vault。编写一个小型 suid exe,它采用其中一个脚本的基名,chdirs 到 /usr/local/lock/vault,删除权限并运行该脚本。包装器脚本的设置与 1 中相同,但它们必须使用“./”前缀路径名调用原始 exe,同时保留在 cwd(库)中。

  3. 使用提升的权限进行切换 (euid=0)。删除原始 exe 上的 suid 位。编写一个小型 suid exe,它采用其中一个脚本的基名(如上面的 1 和 2),并且在不删除权限的情况下调用该脚本(必须具有 #!/bin/bash -p)并允许删除原始 exe本身就有特权。

我认为 3 风险太大,因为很多东西都是在 euid=0 下运行的,包括脚本。

比较 1 和 2 的小 exes:2 只在 euid=0 的情况下执行 chdir(这有多糟糕?),而 1 则打开绑定安装的 suid 命名空间并将 setns 设置为该 fd - 仍然很小,但更多复杂的后果。此外,1 的设置还需要一个服务来创建 suid 挂载命名空间并将其绑定挂载到某处。不多,但有些东西。或者,新的 exe 可以自己创建挂载命名空间,但这使得它变得更加复杂:它必须调用 unshare 并使用提升的权限挂载,这两者都有比 open 和 setns 更多的选项。

我倾向于 2,这似乎是最安全/最简单的,尽管金库设置看起来很笨拙。除非有人能提供更好的方法或看到 2 的问题。

答案1

挂载命名空间可以工作,但比必要的更复杂。

lock/vault 目录技巧并不安全,因为保管库内进程的 /proc/PID/cwd 魔术符号链接允许其他进程 cd 进入保管库(前提是它们具有相同的 uid/gid)。

与解决方案 3 类似,但使用 sgid 代替:编写一个小的 sgid exe。使用没有成员的专用系统组:我们将其称为 mygr。将原来的suid exe修改为root:mygr 4750。现在原来的suid exe只能被mygr的成员调用,这无非就是通过调用新的小sgid-to-mygr来实现。新的小型 sgid exe 仍然控制 suid exe 的使用,执行少数允许的目标脚本之一。因为原始的 suid exe 以完全通用的方式删除权限(已检查),它将把egid设置回rgid,并将euid设置回ruid,因此egid=mygr将是临时的。

脚本仍然需要是 #!/bin/bash -p,以便在执行目标 suid exe 之前不会撤消egid=mygr。

由于新的小 exe 被 sgid 到一个无用的组 (mygr),因此与 suid 到 root 相比,它被利用进行权限升级的机会要小得多。

相关内容