Sudo:默认不允许 shell 转义

Sudo:默认不允许 shell 转义

我无法弄清楚如何禁用任何命令的 shell 转义,以便我可以(这是一个示例!)执行以下操作:

sudo-user ALL=(ALL) NOEXEC: NOPASSWD: ALL

sudoers 手册是这样说的:

一个命令可能有零个或多个与其关联的标签。有八个可能的标记值:NOPASSWD、PASSWD、NOEXEC、EXEC、SETENV、NOSETENV、LOG_INPUT、NOLOG_INPUT、LOG_OUTPUT 和 NOLOG_OUTPUT。一旦在 Cmnd 上设置了标签,Cmnd_Spec_List 中的后续 Cmnd 就会继承该标签,除非它被相反的标签覆盖(即:PASSWD 覆盖 NOPASSWD,NOEXEC 覆盖 EXEC)

但这并没有描述如何设置多个标志。使用逗号似乎不起作用(它将第二个标签视为别名)

更好的是,我想设置一个默认值,所以上面的行是:

defaults NOEXEC     
sudo-user ALL=(ALL) NOPASSWD: ALL

我知道 sudo 可以使用 noexec 进行编译,但在这种情况下这是不切实际的。我也知道这不是全部答案 - 可以通过适当设置 LD_PRELOAD 来颠覆,但这是一个开始。

须藤版本:

Sudo version 1.8.19p2
Sudoers policy plugin version 1.8.19p2
Sudoers file grammar version 45
Sudoers I/O plugin version 1.8.19p2
On RHEL 7.5

答案1

不要这样做。

您赋予sudo-user以任何用户身份运行任何命令的能力。这包括修改的能力 /etc/sudoers使用任何不需要执行子流程的工具。您可能认为排除visudo,但严格来说,您没有需要 visudo编辑/etc/sudoers

例如:

sudo-user$ sudo sed --in-place -e '/^sudo-user/s/NOEXEC://' /etc/sudoers

...并且用户刚刚删除了NOEXEC:限制。

用户可以随意解除的限制并不是真正的限制。


另外,NOEXEC:可能会导致问题。它不仅可以防止 shell 转义:它还可以防止使用sudofrom执行的程序直接启动任何其他程序。这可能会产生很多后果。

例如,如果您sudo-user停止并稍后重新启动cron守护程序(例如,在某些维护期间停止计划作业),则重新启动的cron守护程序将由于限制而无法实际执行任何计划作业NOEXEC:

NOEXEC:存在,以便系统管理员可以将其应用于精心选择的程序,这些程序被发现能够执行其任务而无需exec()任何子进程。盲目地应用到一切会引起问题。


但如果你绝对必须这么做,那么方法如下。

sudoers(5)手册页:

User specification
 User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \
               (':' Host_List '=' Cmnd_Spec_List)*

 Cmnd_Spec_List ::= Cmnd_Spec |
                    Cmnd_Spec ',' Cmnd_Spec_List

 Cmnd_Spec ::= Runas_Spec? SELinux_Spec? Tag_Spec* Cmnd

 Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')'

 SELinux_Spec ::= ('ROLE=role' | 'TYPE=type')

 Tag_Spec ::= ('EXEC:' | 'NOEXEC:' | 'FOLLOW:' | 'NOFOLLOW' |
               'LOG_INPUT:' | 'NOLOG_INPUT:' | 'LOG_OUTPUT:' |
               'NOLOG_OUTPUT:' | 'MAIL:' | 'NOMAIL:' | 'PASSWD:' |
               'NOPASSWD:' | 'SETENV:' | 'NOSETENV:')

这是一个详细的关于如何构造一个的描述用户规范文件的行sudoers。阅读起来可能有点乏味,但它确实包含了您需要的信息。

让我们使用您的示例行来解决这个问题:

sudo-user ALL=(ALL) NOEXEC: NOPASSWD: ALL

整条生产线被称为用户规范, 或者User_Spec

其分解如下:

  • User_List您的示例中只有一个用户:sudo-user
  • Host_List只有一个条目,ALL
  • Cmnd_Spec_List在你的例子中是(ALL) NOEXEC: NOPASSWD: ALL
  • 该行上没有其他: Host_List = Cmnd_Spec_List单位(括号后的星号表明可能有零个或多个这样的附加单位。)

你的Cmnd_Spec_List没有逗号,所以它只有一个Cmnd_Spec

Cmnd_Spec分解为:

  • 可选Runas_Spec:根据您的情况,(ALL)
  • 可选的SELinux_Spec,它在您的示例中不存在
  • 零个或多个Tag_Specs,这是您想了解的部分
  • Cmnd,命令,这就是ALL你的情况。

SingleTag_Spec只是列出的关键字之一,末尾带有冒号,没有明确列出逗号、空格或其他分隔符。该Cmnd_Spec ::=行准确地告诉我们在该行的何处放置空格。由于没有说明如何在标签之间放置空格或任何其他分隔符,因此请勿这样做。

所以,只需将标签一个接一个地放置即可, 像这样:

sudo-user ALL=(ALL) NOEXEC:NOPASSWD: ALL

答案2

您不需要为此添加标签,因为noexec默认输入行也需要一个布尔标志:

noexec

如果设置,则通过 sudo 运行的所有命令都将表现为已设置 NOEXEC 标记,除非被 EXEC 标记覆盖。请参阅下面的 NOEXEC 和 EXEC 的描述以及防止外壳逃逸本手册末尾部分。这个标志是离开默认情况下。

所以你需要的是

Defaults        noexec

这将出现与 telcoM 在 中指出的相同问题他们的答案 。它将阻止visudo运行(因为这需要启动单独的编辑器进程),因此之后撤消更改将变得更加困难。

答案3

结合目前给出的两个答案,这个怎么样:

Defaults noexec
root    ALL=(ALL)       ALL
%wheel  ALL=(ALL)       ALL
sudo-user ALL=(ALL)     EXEC:NOPASSWD:  ALL
fred ALL=(ALL)          NOPASSWD:  user_allowed_commands

其实我建议给予 sudo 用户不受限制的访问权限。这似乎是推荐的方法(至少在 Ubuntu 等中),而不是使用 root。我已经在审核 /etc/sudoers 目录了。这允许 fred 运行“user_allowed_commands”中的命令列表(假设不需要 fork/exec,这似乎不太可能,TBH - 或者我误读了 noexec 正在做什么?)

我想从 @telcoM 添加此内容: 用户可以随意解除的限制并不是真正的限制。

在我看到的所有 SELinux 实现中,它都不是一成不变的,因此任何用户都可以运行 setenforce permissive,并且所有限制都将被删除。

相关内容