需要从 PHP 执行以下行:
$res = shell_exec('sudo sh /home/nicklas/cronjobs/make_account.sh 用户名密码');
问题是执行时没有任何反应。如果我尝试回显 $res 它会显示为空白。我也尝试过使用 system() ,结果相同。我猜它不起作用,因为我需要以 root 访问权限运行脚本,而 www-data 用户默认没有该权限。我将以下行添加到 /etc/sudoers 以希望获得访问权限:
www-data ALL=(ALL:ALL) NOPASSWD: /home/nicklas/cronjobs/make_account.sh
但没有成功。我尝试在中间重新启动 apache,但没有改变任何内容。
我错过了什么吗?
答案1
我强烈反对从网络服务器运行具有更高权限的东西总是一个坏主意。
Web 应用程序的安全问题来自于对用户提供的数据的信任,而不是来自使用该数据的确切进程。
换句话说,如果您不验证和清理您的数据,那么没有更安全通过命名管道将其传递给 root 拥有的进程,而不是编写一个包装脚本来处理该数据并允许 www-data 用户通过 sudo 运行它。
实际上,大部分数据处理/验证/清理应该在数据传递到 sudo 脚本之前完成,这应该 a) 对数据进行最终检查,b) 执行仅有的需要更高权限的操作。
事实上,我认为后者可能更安全,因为这是一个更简单的解决方案,更容易理解……你做的事情越复杂,你就越有可能犯错误。
无论您使用哪种方法(命名管道、sudo 包装器或其他)至关重要的事情是你检查用户提供的数据并确保它符合非常狭窄的定义标准,然后再执行任何事物用它。
网络上有许多关于 CGI 安全性的文章和指南,其中包括 stackexchange 网站上的几篇文章和指南,但一些常见主题是:
- 在您检查和/或修改数据以确保其安全之前,将数据视为“受污染”且不可信。
- 检查数据 - 例如测试它是否与允许或禁止字符的正则表达式匹配。最安全的选择是在出现任何奇怪的情况时中止,否则使用正则表达式或其他内容进行转换以删除潜在的不安全元素。
- 总是如果将数据传递给外部 shell 脚本,则引用数据。例如,shell 脚本应该在变量周围使用双引号。
- 同样,当将数据插入数据库时,您应该使用支持占位符值的数据库库,而不是依赖于转义或引用。这里这是一个幽默的说明。
我可以继续说下去,但是这里的答案有太多需要总结的内容 - CGI 安全性是一个广泛的主题。尝试用谷歌搜索CGI安全或者验证 CGI 输入
你对安全的态度是“我不在乎,因为只有我在用它”,我感觉就像是我在给你一把上膛的猎枪,让你用它来炸掉你的脚,但搬起石头砸自己的脚是一次宝贵的学习经历。这是创建用户帐户的简单脚本。它需要 root 权限。
该脚本依赖于 adduser,它在 debian 和 debian 派生系统以及其他系统上可用。如果您的系统上没有,请修改为使用 useradd。
#! /bin/bash
# make the script abort on any error
set -e
U="$1"
P="$2"
[ -z "$U" ] && echo "Error: No username provided" >&2 && exit 1
[ -z "$P" ] && echo "Error: No password provided" >&2 && exit 1
# simple check - only allow lower-case letters and digits in usernames.
[ "$U" !~ '^[a-z0-9]*$' ] && echo "Error: Invalid Username" >&2 && exit 1
# create user if they don't already exist
if ! getent passwd "$U" > /dev/null ; then
# create the user using adduser, must provide the gecos field
# and disable the password so adduser doesn't ask for them.
adduser --gecos "$U" --disabled-password "$U"
# now change the password
echo "$U:$P" | chpasswd
else
echo "Error: Username already exists" >&2
exit 1
fi
将脚本保存在某处,并使用 chmod 使其可执行。
要允许 www-data 以 root 身份运行而无需密码,请编辑 /etc/sudoersvisudo
并添加以下内容:
Cmnd_Alias APACHEADDUSER = /path/to/makeaccount.sh
www-data ALL = NOPASSWD: APACHEADDUSER
答案2
出于安全原因,您永远不应该尝试使用具有比其自然拥有的更多权限的用户 www-data 来执行某些操作。前段时间 Apache 访问被转移到 www-data 是有原因的。如果您需要以 root 身份在计算机上执行某些操作 - 并且更改密码或创建帐户就是这个“操作” - 您应该构建一个界面。让 php 脚本将某些内容放在某处,并通过从 root 执行的脚本扫描它并在那里处理它。您可以创建一个包含要添加到 www-data 可以访问的目录中的用户的文件,然后每 5 分钟(或更短时间)通过 root-cronjob 执行此操作,并将文件移动到带有时间戳的完成文件夹中以进行控制关于正在发生的事情。