首先,我们仅讨论 Debian/Ubuntu 操作系统。 (如有冒犯请见谅,因为我只熟悉这2个)
第二,我们讨论的是仅具有 sudo 权限的非 root 用户。
每次我要使用 sudo 权限运行命令时,我总是问自己应该使用sudo bash -c 'command'
还是仅仅使用 sudo sudo command
,这对我来说有点痛苦。
因为有些情况不能sudo command
直接起作用,例如,
sudo echo "smth" >> /etc/privilegedfile
但使用sudo sh -c "echo 'smth' >> /etc/privilegedfile"
或似乎总是有效sudo bash -c "echo 'smth' >> /etc/privilegedfile"
(或者使用其他工具,比如tee
让它发挥作用。)
所以问题是,
是否存在sudo bash -c 'command'
不能执行但只能sudo command
执行的场合(例外)?
sudo bash -c
使用而不是永远使用是个好主意吗sudo
?
答案1
sudo bash -c
和 之间sudo
有很大不同,因为sudo
可以配置为向运行特定命令的特定用户授予权限。因此,您可能会发现自己处于允许运行sudo command
(对于 的某个值command
)但不允许运行的设置中sudo bash
。
一般来说,尽可能具体是个好主意,所以优先sudo command
考虑sudo bash -c command
.
答案2
与 sudo 一起使用bash -c
可能比单独使用要危险得多sudo
。在 shell 中运行命令时,shell 以各种方式处理和扩展许多特殊字符。例如rm *.txt
,您正在输入的 shell(通常是 bash)将 *.txt 扩展为当前文件夹中以 .txt 结尾的文件列表。出于对简单性和安全性的渴望,sudo 命令不会这样做。相反,它只是直接使用您传递给它的参数直接运行命令。例如,假设您在 shell 中运行以下命令:
$ file=/etc/passwd
$ sudo vim $file
$ ls *.txt
hello.txt world.txt
$ sudo rm *.txt
第一行设置一个变量 ,$file
在当前 shell 中运行 sudo 命令sudo vim /etc/passwd
,然后列出并 sudo 删除所有文本文件。在 sudo 有机会看到或运行它之前,shell 就扩展了该变量和文件名通配符。在最后一行,当 sudo 被调用时,它看到它被赋予了三个参数:rm
、hello.txt
和world.txt
。然后,它rm
以用户 root 身份调用,仅使用两个参数,无需进一步处理。如果我在它周围使用引号,例如,,sudo rm "*.txt"
那么 sudo 会看到并调用rm
带有一个参数的命令*.txt
。 rm 命令会按字面意思理解并尝试删除名为“*.txt”的文件,但发现它不存在。它甚至不会查看另外两个以 .txt 结尾的文件。该扩展是由 shell 完成的。
为了让大家明白这一点,当您去掉 shell 使生活变得更轻松的魔力时,我上面列出的命令必须直接编写,而不需要任何变量或通配符,如下所示:
$ sudo vim /etc/passwd
$ ls hello.txt world.txt
hello.txt world.txt
$ sudo rm hello.txt world.txt
ls
、rm
和本身都不sudo
知道如何扩展 *.txt 或$file
,这是 shell 的工作。现在,让我们看看bash -c
sudo 中哪些地方可能存在危险。请不要在家尝试这个:
$ file=/etc/passwd
$ sudo vim $file
# Take a short break from your computer here...
$ file="/lets/be/malicious; cp /dev/zero /dev/sda"
$ sudo vim $file # Might see a harmless error here
$ sudo bash -c "vim $file" # Goodbye hard-drive
虽然我不得不承认,这是一个非常人为的例子,但我希望不难想象这里可能发生的一些潜在危险。问题是您现在为 shell 提供了以 root 身份扩展元字符的功能。假设您离开后,有人修改了文件变量,在其中嵌入了恶意命令,该命令会擦除您的硬盘驱动器。使用以前的语法sudo vim $file
,它将扩展为常规的非特权用户并失败。在第二次使用中,它将扩展 $file 以及其中嵌入的所有魔力,以在以 root 身份运行的成熟 shell 中运行。