我们可以阻止在 Linux 中以 root 身份执行命令吗?

Sae*_*ati 17 permissions command-line bash chmod

有这个脚本很难阅读和调试。

在它的某个地方,它有这样的命令:

sudo chmod -R 777 /$some_var/$another_var
Run Code Online (Sandbox Code Playgroud)

换句话说,它动态创建一条路径,然后递归地授予该路径权限。

但是,由于它需要互联网连接并下载内容,有时这些变量由于错误而为空,并且会执行以下命令:

sudo chmod -R 777 /
Run Code Online (Sandbox Code Playgroud)

这会破坏操作系统。我们需要再次重新安装它。

我们正在编写脚本,使其变得更好、更有弹性。但是,有没有办法阻止用户执行该命令root

我的意思是,如果路径为 ,我希望该命令不可执行/,即使对于root用户而言:

sudo chmod -R 777 /
Run Code Online (Sandbox Code Playgroud)

mur*_*uru 48

如果您专门询问有关sudo chmod -R 777 /Ubuntu 的问题,那么您很幸运。GNU 工具有一个选项:--preserve-root. 来自GNU 文档

2.9/特殊处理

某些命令可以对整个层次结构进行破坏性操作。[...] 由于此类命令的合法用途非常少,GNU rm通常拒绝在任何解析为 /. 如果您确实想尝试删除系统上的所有文件,可以使用该--no-preserve-root选项,但该--preserve-root选项指定的默认行为对于大多数用途来说更安全。

命令chgrp,chmodchown还可以对整个层次结构进行破坏性操作,因此它们也支持这些选项。[...] 传统和 POSIX 要求这些命令在 上递归操作/,因此它们默认为--no-preserve-root,但使用该--preserve-root选项使它们对于大多数用途来说更安全。--preserve-root为了方便起见,您可以在别名或 shell 函数中指定。

请注意,该--preserve-root选项还确保chgrp即使 在取消引用指向 的符号链接时也chown不会修改。//

因此,修改您的脚本以使用:

sudo chmod -R 777 --preserve-root /$some_var/$another_var
Run Code Online (Sandbox Code Playgroud)

请注意,我不容忍使用chmod -R 777. 绝对必要的情况极为罕见chmod -R 777


您还可以使用set -u使脚本将未设置的变量视为错误,或使用${var:?message}将未设置的变量的特定实例视为错误:

$ message="Unset/empty variable not allowed"
$ sudo chmod -R 777 --preserve-root "/${some_var:?$message}/${another_var:?$message}"
bash: some_var: Unset/empty variable not allowed
Run Code Online (Sandbox Code Playgroud)

(默认消息是:parameter null or not set。)

在 Docker 容器中测试:

root@d9c4e4427d7a:/# chmod -R 777 --preserve-root "/${some_var:?$message}/${another_var:?$message}"
bash: some_var: Unset/empty variable not allowed
root@d9c4e4427d7a:/# some_var=/
root@d9c4e4427d7a:/# another_var=////
root@d9c4e4427d7a:/# chmod -R 777 --preserve-root "/${some_var:?$message}/${another_var:?$message}"
chmod: it is dangerous to operate recursively on '/'
chmod: use --no-preserve-root to override this failsafe
Run Code Online (Sandbox Code Playgroud)


Rin*_*ind 13

我们可以阻止在 Linux 中以 root 身份执行命令吗?

不。

我们可以阻止 Linux 中的脚本执行命令吗?

是的。不要使用它并自己制作。例如,您可以创建一个别名 fprchmod并对其有效性进行一些检查并执行它chmod

这很糟糕:

sudo chmod -R 777 /$some_var/$another_var
Run Code Online (Sandbox Code Playgroud)
  • sudo不属于脚本内部。
  • 777总是不好。750最多当您有超过 1 个用户时,并且700应该优先在单机上使用。
  • 始终必须检查$some_varAND是否$another_var具有正确的值。健全性检查是脚本的重要组成部分。如果这些值来自不受信任的来源(例如用户通过命令行执行或通过编辑配置提供变量),则更是如此。

意思是如果路径为 ,我希望该命令不可执行/,即使对于 root 用户也是如此:

显而易见的答案是在评估变量的命令之前添加健全性检查。您还可以使用别名chmod来执行您自己的命令来检查值。

它必须在脚本内部:对空的检查还不够好:$some_var="/////////////"同样糟糕;)

  • “sudo 不属于脚本”。在某些情况下确实如此。有好几次,我发现自己编写了一个应该由所有用户(或特定组)可执行的脚本,但包含一些只能以 root 身份(或其他用户 - 通常是运行某些守护进程的用户,例如 apache)执行的命令)。在这种情况下,在脚本中使用 sudo (当然与 `/etc/sudoers.d` 中的特定配置文件一起,仅允许使用该特定命令)是一个明显的解决方案。但我同意在脚本中特别使用“sudo chmod”是一个坏主意。 (7认同)
  • -1 OP专门询问“sudo”命令,并且完全有可能使用该机制(使用白名单/黑名单/“!”运算符)做他想做的事情......很明显,最好的解决方案是修复(或首先删除...)脚本,但这不是他要的。IMO 不需要重新构建这个问题,因为 OP 已经在编写脚本了。 (2认同)

Raf*_*ffa 8

您可以使用 Bash 的扩展测试括号[[ ... ]]来预先检查if语句...以下内容将检查是否$path包含除正斜杠和空格之外的字符以及解析路径本身,如果其中一个或两个都将评估为 false两个参数$some_var$another_var未设置或为空,或者如果两者都是斜杠或全部空格,或者如果$path解析为/...,如下所示:

path="/${some_var:-EMPTY}/${another_var:-EMPTY}"

if [[ "$path" = *[!\ /]* && "$(realpath "$path" 2>/dev/null)" != "/" && ! "$path" =~ "EMPTY" ]]
then
  # your command using those variables here
  # chmod -R 777 "$path"
  echo "Directory is not root"
fi
Run Code Online (Sandbox Code Playgroud)

注意:改进以解决黑客概率(由@grok的评论提出......谢谢@grok)等。


Dmi*_*yev 7

使关键脚本更安全的一个简单有效的方法是set -e在开头添加。这将停止执行任何错误(除了条件之外的任何命令的非零返回代码)。

这并不会神奇地使任何命令安全,但如果$some_var由前一个命令设置,并且该命令失败,则脚本将停止,而不是使用空变量进一步执行。它的一大优点set -e是它经常捕获您可能没有想到的故障。缺点是您现在必须确保您编写的每个命令都成功。例如,您不能只是rm /tmp/file清理可能不存在的临时文件,因为尝试删除不存在的文件现在将停止您的脚本。

通常,编写良好的脚本会尝试显式捕获所有明显的错误,但set -e无论如何都会使用它来覆盖剩余的故障。


Art*_*ild 5

做这个:

# if both of the variables are not empty
if [[ -n "$some_var" && -n "$another_var" ]]
then
    # run the chmod command as intended
    sudo chmod -R 777 /$some_var/$another_var
else
    # only do this if you don't want the script to continue, but to exit with an error message
    echo "Error - exiting"
    exit
fi
Run Code Online (Sandbox Code Playgroud)

如果任何变量可能包含一串斜杠(/字符),您也需要检查这一点。