如何安全地将变量传递给启用了root的脚本?


13

这个问题是完全笼统的,不仅适用于我的情况,而且...我有一个小型busybox设备,希望非root用户能够使用root特权执行特定脚本。例如,类似以下这样$1的小脚本来启用DHCP,其中在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

而不是要求输入密码(这是我想要的,因为我希望joe能够编写此脚本)。

现在..我知道(或者至少我认为这样做),$1在可以轻松使用root特权运行的脚本中使用是一个可怕的想法,因为您可以向其中注入任何内容。

那么...解决此问题的最佳方法是什么?我如何让Joe用root特权执行我想做的事情,如何允许他传入变量(或者像使用环境变量那样有效地传递变量),同时又不对注入攻击敞开大门?

Answers:


14

如果配置了重置环境在下面运行shell脚本sudo是安全。相反,如果不重置环境,那么即使您的脚本不使用其参数,运行shell脚本也不是安全的(请参阅在shell脚本上允许setuid)。确保in 或此选项是编译时的默认值(应包含)。sudosudoDefaults env_reset/etc/sudoerssudo sudo -V | grep envReset the environment to a default set of variables

使用脚本参数没有特别的危险。$1是一个字符串,您需要确保将其用作字符串。(例如,不要这样做eval "$1"。)显然,在此尤其重要的是,不要对变量的内容进行假设,并在所有变量替换处都用双引号引起来(即write "$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"

需要考虑的其他事项可能会影响该命令的行为:当前的工作目录以及stdin,stdout,stderr指向的内容,信号处理程序和ulimits。例如,通过允许核心转储(在<kbd> Ctrl-\ </ kbd>上),您可以允许用户乱抛垃圾/运行/锁定,这在我的系统上是大小非常有限的tmpfs,并且可能允许DoS。
斯特凡Chazelas

5

您应该将传递的输入与已知的良好模式进行匹配。

例如,看起来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

请注意,尚未对regexp进行测试,您有责任确保regexp不允许任何危险的事情。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.