以根用户身份执行Python脚本(seteuid vs c-wrapper)

13

我有一个在Python脚本中的任务需要root权限,希望从Django(www用户)调用。一开始我认为可以使用Python的os.seteuid()函数并设置脚本的setuid位,但后来意识到这会要求设置Python本身的setuid位,而这可能是不可取的。据我所知,如果使用sudo也将面临相同的问题,而我真的想避免使用sudo。

此时,我考虑编写一个C语言包装器,使用seteuid并以root身份调用我的Python脚本,将必要的参数传递给它。我是否应该这样做,还是应该找其他解决方案?


2
为什么不使用subprocesssudo将其作为外部进程执行,尽管这一切都让人感到不妙。 - Anders
因为这将需要授予www以root身份运行Python的权限 :( - kwl34
1
这里的主要问题在于setuid和常见的sudo操作不像对待二进制文件那样适用于单个Python脚本,而是适用于Python解释器本身。 - kwl34
3个回答

14

在Python中,sudo不需要setuid位。你可以仅为一个命令启用sudo,而不需要任何参数:

 www          ALL=(ALL)       NOPASSWD:  /root/bin/reload-stuff.py ""

如果你的脚本不带任何参数,不能被www用户覆盖,并且sudo执行“env_reset”(在大多数发行版中是默认设置),那么这将是安全的。

你可以接受参数,但是要非常小心 -- 不要使用输出文件名,确保验证所有输入。在这种情况下,从sudo行末尾删除“”。


有趣!我会立即测试这个。然而,我的脚本确实需要参数,虽然很简单。你认为只要我的Python脚本对这些参数进行严格匹配,就可以了吗? - kwl34
你可以接受尽可能长的参数,只要你小心处理它们。 - theamk
“ALL=(root)” 可能更好,可以限制脚本只在 root 用户下运行,而不是其他用户。最好只限制于你所需的内容。 - CivFan
@theamk 环境重置是否足以防止用户加载自己的站点包,从而欺骗 'reload-stuff' 运行恶意代码?我特别关注 virtualenv 或 PEP-370 - gcscaglia
env_reset会将HOME设置为目标用户的主目录(例如/root),并清除所有其他环境变量--因此,是的,虚拟环境将被忽略,并且用户站点将从root的主目录中使用,这将是安全的。 - theamk

3
正确的做法被称为特权分离:明确标识必须使用升高权限完成的最小任务集。编写一个单独的守护程序和一种尽可能受限的通信任务方式。将此守护程序作为具有升高权限的另一个用户运行。虽然需要更多的工作,但也更加安全。
编辑:使用setuid包装器也可以满足特权分离的概念,尽管我建议将Web服务器设置为chroot,并挂载chroot文件系统nosuid(这将破坏该功能)。

这是我建议使用C封装二进制文件。它通过seteuid()提供了一个有限的接口,使用户可以访问需要特权的特定函数。 - kwl34
是的,你说得对,那样做可以。我没有考虑到这一点,因为我建议将Web服务器chroot并将其挂载到Web服务器可访问的文件系统nosuid上。 - knitti
我想推荐使用sudo而不是C包装器。很容易忘记清除PYTHONSTARTUP或其他环境变量,但是带有env_reset的sudo会为您完成这项工作。 - theamk

1

sudo 允许您限制传递给程序的参数。来自 man sudoers

john           ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root*

On the ALPHA machines, user john may su to anyone except root but
he is not allowed to specify any options to the su(1) command.

因此请使用sudo。当然,您需要特别小心根访问权限-确保只有root可以修改脚本本身和任何父目录,并且脚本是安全的,只执行必须作为root运行的绝对最低限度的操作。


我可能错了,但这仍然需要给www用户sudo root访问Python解释器本身,并且您基本上正在使用sudo的参数解析器仅允许运行脚本。这正确吗?如果是这样,那么也很容易考虑传递给脚本的参数(键/值)。 - kwl34
是的,没错。而且,这应该很容易,但我建议通过stdin/stdout进行通信。不幸的是,由于这是一个安全问题,读取“man sudoers”确实没有其他选择。 - Petr Viktorin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接