我正在编写一个基于Python的Web服务器,它应该能够执行“插件”,以便可以轻松扩展功能。
为此,我考虑了有多个文件夹(每个插件一个)和一些shell / python脚本的方法,这些脚本以可能发生的不同事件的预定义名称命名。
一个例子是拥有一个on_pdf_uploaded.py
文件,该文件在PDF上传到服务器时执行。为此,我将使用Python的子进程工具。
为了方便和安全,这将允许我使用Unix环境变量来提供进一步的信息并设置进程的工作目录(cwd),以便它可以访问正确的文件而无需找到它们的位置。
由于插件代码来自不受信任的来源,我希望尽可能安全。我的想法是在子进程中执行代码,但是将它放入具有不同用户的chroot jail中,这样它就无法访问服务器上的任何其他资源。
不幸的是我找不到任何关于此的内容,我不想依赖不受信任的脚本将自己置于监狱中。
此外,我也不能将主/调用进程放入chroot jail,因为在服务器回答其他请求时,插件代码可能同时在多个进程中执行。
所以这就是问题:如何在chroot jail中执行子进程/脚本,以最小的权限保护服务器的其余部分不被错误的,不受信任的代码损坏?
谢谢!
答案 0 :(得分:4)
也许是这样的?
# 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)
This非常有用,而且我只是偷了那些代码,所以对那个人的称赞是一个不错的例子。
答案 1 :(得分:3)
创建jail后,您可以从Python源代码中调用os.chroot
进入其中。但即便如此,解释器已经打开的任何共享库或模块文件仍然是开放的,我不知道通过os.close
关闭这些文件的后果是什么。我从未尝试过。
即使这样可行,设置chroot也是一个大问题,所以要确保这个好处值得付出代价。在最坏的情况下,您必须确保整个Python运行时包含您打算使用的所有模块,以及所有相关程序和共享库以及来自/bin
,/lib
等的其他文件。在每个被监禁的文件系统中。当然,这样做不会保护其他类型的资源,即网络目的地,数据库。
另一种方法是将不受信任的代码作为字符串读入,然后exec code in mynamespace
,其中mynamespace
是一个字典,仅定义要向不受信任的代码公开的符号。这将是Python VM中的一种“监狱”。您可能必须先解析源代码,首先查找import
语句之类的内容,除非替换内置的__import__
函数将截取(我不确定)。