2012-07-30 24 views
10

我正在編寫一個基於Python的Web服務器,它應該能夠執行「插件」,以便可以輕鬆擴展功能。Python:使用chroot和chjail保護不受信任的腳本/子進程?

爲此,我考慮了爲每個插件提供多個文件夾(一個用於每個插件)和一些shell/python腳本的方法,這些文件以可能發生的不同事件的預定義名稱命名。

一個示例是在將PDF上載到服務器時執行on_pdf_uploaded.py文件。要做到這一點,我會使用Python的子進程工具。

爲了方便和安全,這將允許我使用Unix環境變量來提供進一步的信息並設置進程的工作目錄(cwd),以便它可以訪問正確的文件而不必查找它們的位置。

由於插件代碼來自不受信任的來源,因此我想盡可能保證它的安全。我的想法是在子進程中執行代碼,但將其與不同用戶的chroot jail放在一起,以便它不能訪問服務器上的任何其他資源。

不幸的是我找不到任何關於這個,我不想依靠不信任的腳本把自己陷入監獄。

此外,我不能把主/調用過程放到chroot jail中,因爲插件代碼可能在服務器應答其他請求的同時在多個進程中執行。

所以,這裏是一個問題:如何在一個chroot jail中執行子進程/腳本,並具有最小權限來保護服務器的其他部分免受錯誤的,不受信任的代碼的破壞?

謝謝!

+0

這真的是你的工作嗎?他們不應該知道他們在運行什麼代碼嗎?無論...這有幫助嗎? [os.chroot()](http://docs.python.org/library/os.html#os.chroot)。另外,'os'已經得到好東西以便與uid混淆等。因此,創建一個新進程(os.fork()?),然後os.setuid然後os.execle()。 – Logan 2012-07-30 16:44:38

回答

2

創建你的監獄後,你會從你的Python源調用os.chroot進入它。但即使如此,解釋器已經打開的任何共享庫或模塊文件仍然是開放的,我不知道通過os.close關閉這些文件的後果是什麼;我從來沒有嘗試過。

即使這樣做,設置chroot也是一件大事,所以確保好處是值得的。在最糟糕的情況下,您必須確保整個Python運行時包含您打算使用的所有模塊,以及所有依賴程序和共享庫以及其他來自/bin,/lib等的文件,均可在每個有監控的文件系統中使用。當然,這樣做不會保護其他類型的資源,即網絡目的地,數據庫。

另一種方法是將不受信任的代碼讀作字符串,然後exec code in mynamespace其中mynamespace是一個字典,它只定義了您想暴露給不可信代碼的符號。這將會是Python VM中的「監獄」。您可能需要首先解析源代碼,例如import語句,除非替換內置的__import__函數會攔截(我不確定)。

+0

我使用動態代碼加載方法,因爲它提供了數據交換和異常處理的最佳靈活性。 – BastiBen 2012-09-22 08:11:42

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]) 

編輯:想用叉子(),但我並沒有真正理解它的所作所爲。看着它。新的 代碼!

# 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

這幾乎解決了我的問題。由於在virtualenv中安裝了psutil以及用戶權限,這件事很棘手,但是在我修復了一些try/error之後。 – coya 2017-08-27 19:36:30

+0

@habnabit你可以詳細說明你的編輯嗎?我不清楚訂單爲什麼重要,我認爲如果它有安全隱患,應該在答案中更明確地提出。 – Logan 2017-10-17 19:51:34

+1

@Logan https://stackoverflow.com/a/11062896 – habnabit 2017-10-18 00:25:32

相關問題