![如何安全地将变量传递给启用 root 的脚本?](https://linux22.com/image/16931/%E5%A6%82%E4%BD%95%E5%AE%89%E5%85%A8%E5%9C%B0%E5%B0%86%E5%8F%98%E9%87%8F%E4%BC%A0%E9%80%92%E7%BB%99%E5%90%AF%E7%94%A8%20root%20%E7%9A%84%E8%84%9A%E6%9C%AC%EF%BC%9F.png)
这个问题是完全普遍的,不仅适用于我的情况,但是......我有一个小型的busybox设备,我希望非root用户能够以root权限执行特定的脚本。例如,类似于这个启用 DHCP 的小脚本,其中$1
在 cmdline (!!) 上发送的唯一变量 () 是要发送的主机名:
#!/bin/bash
udhcpc -b -i eth0 -h $1
像这样运行 udhcpc 需要 root 访问权限,因此为此我计划修改/etc/sudoers
以包含此行:
joe ALL = NOPASSWD: /path/to/enable_dhcp.sh
这应该使“joe”能够通过简单地运行以下命令轻松地以 root 权限运行该脚本:
sudo /path/to/enable_dhcp.sh
并且不要求输入密码(这就是我想要的,因为我希望乔能够编写此脚本)。
现在我知道(或者至少我认为)在$1
可以轻松以 root 权限运行的脚本中使用是一个可怕的想法,因为您可以将任何您想要的东西注入其中。
那么...处理这个问题的最佳方法是什么?我如何让 joe 使用 root 权限做我想做的事情,允许他传入一个变量(或者像使用环境变量一样有效地这样做),同时又不会受到注入攻击?
答案1
在下面运行 shell 脚本sudo
是安全的前提是sudo
是配置为重置环境。相反,如果sudo
不重置环境,那么运行 shell 脚本就不安全,即使您的脚本不使用其参数(请参阅允许在 shell 脚本上设置 setuid)。确保您有Defaults env_reset
in/etc/sudoers
或此选项是编译时默认选项(sudo sudo -V | grep env
应包含Reset the environment to a default set of variables
)。
使用脚本参数没有特别的危险。$1
是一个字符串,您需要确保将其用作字符串。 (例如,不要这样做eval "$1"
。)显然,这里特别重要的是不要对变量的内容做出假设,并且要所有变量替换都用双引号引起来(即写"$1"
,不写$1
)。请注意,在变量替换周围添加双引号并不是特定于以特权运行的脚本,而是您必须始终执行的操作。
您可能需要进一步验证该参数,具体取决于对udhcpc
看起来不像主机名的内容的处理方式。例如,这将执行第一次语法检查:
#!/bin/sh
case "$1" in
*[!:-.0-9A-Za-z]*|-*) echo 1>&2 "Badly formed host name!"; exit 3;;
esac
udhcpc -b -i eth0 -h "$1"
答案2
您应该将传递的输入与已知的良好模式进行匹配。
例如,看起来 IP 地址可能是您的有效输入。所以你可以使用这样的东西:
if [[ "$1" =~ ^[0-9]?[0-9]?[0-9].[0-9]?[0-9]?[0-9].[0-9]?[0-9]?[0-9]$ ]]
then
udhcpc -b -i eth0 -h "$1"
else
echo "Don't mess with me pork chop."
fi
请注意,该正则表达式尚未经过测试,您有责任确保您的正则表达式不允许任何危险的内容。