如何正确运行setuid任务?

如何正确运行setuid任务?

假设有一个php网站,我想根据网站代码执行在防火墙级别阻止一个ip。该站点在非 root 用户下运行。

我打算将 IP 从站点代码传递到脚本(只能写入 root),例如

#!/bin/bash
function validate_ip()
{ ... code here ...}
if validate_ip $1; then 
    /usr/sbin/iptables -I INPUT -s $1 -j DROP
    echo 'blocked'; 
else 
    echo 'bad IP $1'; 
fi

使用 suid 位。我想添加额外的 IP 验证以避免 XSS 和其他不好的事情(如果你愿意,可以考虑偏执),所以不想让网站直接调用 iptables。

该脚本不起作用,can't initialize iptables table 'filter': Permission denied (you must be root)因为bash 删除 suid 位

有解决方法:允许sudo 中的 iptables但我认为它不安全。我没有时间/可能性来开发/购买可以完成任务的二进制文件。有人建议对脚本进行二进制包装,但我犹豫了,也许有更好的方法?

所以,问题是:如何允许非 root 应用程序以安全的方式阻止 iptables 防火墙中的 ip?

答案1

不要让 bash 脚本成为 suid root,而是通过 sudo 运行 bash 脚本。作为一个附带好处,这还可以让您轻松锁定谁可以以 root 身份运行您的脚本以及传递的参数。例如,您可以只允许:

phpuser ALL=(root) NOPASSWD: /usr/local/sbin/your-script [0-9][0-9][0-9].[0-9][0-9][0-9].[0-9][0-9][0-9].[0-9][0-9][0-9]

然后确保您的 PHP 脚本始终将每个 IP 地址八位字节的格式设置为三位数字。

如果让 PHP 调用 sudo 太困难(不应该这样!),您可以让脚本自己执行此操作,例如:

#!/bin/sh

[ "$(id -u)" -eq 0 ] || exec sudo -- "$0" "$@"
# rest of script here

(我不完全确定 iptables 会满意前导 0,如果不满意,您可以将它们去掉)。

PS:请在 shell 脚本中引用您的变量:

if validate_ip "$1"; then 
    /usr/sbin/iptables -I INPUT -s "$1" -j DROP
    # ⋮

相关内容