Python itself?
例如:
>>> import code
>>> def host_func():
... print("Hello old chap!")
...
>>> c = code.compile_command("print(\"Script says hello!\"); host_func()")
>>> exec(c)
Script says hello!
Hello old chap!
exec
讓我們你是明確的關於從主機環境,你想通過兩個可選參數locals
和globals
揭露什麼。
在這個例子中,我明確了腳本將訪問的全局變量。請注意,我可以在這裏「創建」變量,或爲現有函數提供另一個名稱。這是一個指向函數和數據的字典。
>>> import code
>>> def secret():
... print("What?! I don't even... get out of here.")
...
>>> def public():
... print("Hello stranger.")
...
>>> c = code.compile_command("secret(); public()")
調用此包含兩個功能的全局,指回已經存在的得出:
>>> exec(c, {"secret": secret, "public": public})
What?! I don't even... get out of here.
Hello stranger.
現在,當我忽略secret
,劇本再也找不到它。
>>> exec(c, {"public": public})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<input>", line 1, in <module>
NameError: name 'secret' is not defined
在這裏我重新定義secret
一起:
>>> exec(c, {"public": public, "secret":lambda: print("Haha! Doppelganger.")})
Haha! Doppelganger.
Hello stranger.
由於lazyr在評論中提到有安全問題。上面的例子讓腳本幾乎可以做它想做的事情。在某些情況下,這是不可接受的。
有一些東西可以做,以阻止它:
- 絕育
__builtins__
,只允許「白名單」的內置功能。
- 難以導入模塊。
例如,這裏是你如何bork import
語句(在Py2中。*內建爲__builtins__
):
>>> import builtins
>>> def no_import(*args, **kwargs):
... raise ImportError("I cannot let you do that, Dave.")
...
>>> builtins.__import__ = no_import
>>> import os
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in no_import
ImportError: I cannot let you do that, Dave.
由此得出,我們可以通過在全局參數我們自己builtins
:
>>> import code
>>> evil_code = "import os; import stat; os.chmod(\"passwords.txt\", stat.S_IROT
H);"
>>> compiled = code.compile_command(evil_code)
>>> def no_import(*args, **kwargs):
... raise ImportError("I cannot let you do that, Dave.")
...
>>> exec(compiled, {"__builtins__": {"__import__": no_import}})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<input>", line 1, in <module>
File "<stdin>", line 2, in no_import
ImportError: I cannot let you do that, Dave.
一個警告,不過,這將博克之後發生的所有進口。將它替換爲允許導入列入白名單的模塊的版本可能會更好。
最後,我不確定這會完全保護你。一些狡猾的人可能很好的規避它。但是最明顯的違規行爲至少應該是不鼓勵的。
+1所以你通過了5000個榮譽里程碑。也許你應該提到一些關於安全問題的內容? 'open(「/ important/file」,「w」)。write(「stuff」)'等 –
@lazyr:噢謝謝:D ...我會用蛋糕來慶祝。是的,我正在考慮這個問題。我可以補充一點。 – Skurmedel
牆壁文字對我造成+400傷害。 – Skurmedel