12

我正在编写一个基于 Python 的 Web 服务器,它应该能够执行“插件”,以便轻松扩展功能。

为此,我考虑了在其中拥有多个文件夹(每个插件一个)和多个 shell/python 脚本的方法,这些脚本以可能发生的不同事件的预定义名称命名。

一个例子是on_pdf_uploaded.py当一个 PDF 上传到服务器时执行一个文件。为此,我将使用 Python 的子流程工具。

为了方便和安全,这将允许我使用 Unix 环境变量来提供更多信息并设置进程的工作目录 (cwd),以便它可以访问正确的文件而无需找到它们的位置。

由于插件代码来自不受信任的来源,我想让它尽可能安全。我的想法是在子进程中执行代码,但将其放入具有不同用户的 chroot 监狱,这样它就无法访问服务器上的任何其他资源。

不幸的是,我对此一无所知,而且我不想依靠不受信任的脚本将自己关进监狱。

此外,我也不能将主/调用进程放入 chroot 监狱,因为插件代码可能在服务器响应其他请求时同时在多个进程中执行。

那么问题来了:如何在 chroot 监狱中以最低权限执行子进程/脚本,以保护服务器的其余部分不被错误的、不受信任的代码损坏?

谢谢!

4

2 回答 2

5

也许是这样的?

# main.py
subprocess.call(["python", "pluginhandler.py", "plugin", env])

然后,

# pluginhandler.py
os.chroot(chrootpath)
os.setgid(gid) # Important! Set GID first! See comments for details.
os.setuid(uid)
os.execle(programpath, arg1, arg2, ..., env)
# or another subprocess call 
subprocess.call["python", "plugin", env])

编辑:想使用 fork() 但我真的不明白它做了什么。查了一下。新代码!

# main.py
import os,sys
somevar = someimportantdata
pid = os.fork()
if pid:
    # this is the parent process... do whatever needs to be done as the parent
else:
    # we are the child process... lets do that plugin thing!
    os.setgid(gid) # Important! Set GID first! See comments for details.
    os.setuid(uid)
    os.chroot(chrootpath)
    import untrustworthyplugin
    untrustworthyplugin.run(somevar)
    sys.exit(0)

很有用,我几乎只是偷了那个代码,所以感谢那个人的一个体面的例子。

于 2012-07-30T17:05:42.957 回答
3

创建你的监狱后,你会os.chroot从你的 Python 源调用进入它。但即便如此,解释器已经打开的任何共享库或模块文件仍然是打开的,我不知道关闭这些文件的后果是什么os.close;我从来没有尝试过。

即使这样可行,设置 chroot 也是一件大事,因此请确保其收益物有所值。在最坏的情况下,您必须确保整个 Python 运行时以及您打算使用的所有模块,以及所有依赖程序和共享库以及来自 等的其他文件/bin/lib每个被监禁的文件系统中都可用。当然,这样做不会保护其他类型的资源,例如网络目的地、数据库。

另一种方法是将不受信任的代码作为字符串读入,然后exec code in mynamespace在哪里mynamespace有一个字典,只定义您想要向不受信任的代码公开的符号。这将是 Python VM 中的“监狱”。您可能必须首先解析源代码以查找import语句之类的内容,除非替换内置__import__函数会拦截它(我不确定)。

于 2012-07-30T16:43:06.153 回答