Я пишу приложение, в котором пользователи могут вводить python script и выполнять его в песочнице. Мне нужно, чтобы код exec'ed не импортировал определенные модули, поэтому вредоносный код не будет проблемой. Есть ли способ сделать это в Python?
Предотвращение импорта кода Python из определенных модулей?
Ответ 1
Если вы поместите None в sys.modules для имени модуля, в не будет импортироваться...
>>> import sys
>>> import os
>>> del os
>>> sys.modules['os']=None
>>> import os
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named os
>>>
Ответ 2
Вы проверили статью python.org на SandboxedPython, а связанная статья?
Обе страницы имеют ссылки на другие ресурсы.
В частности, PyPi RestrictedPython позволяет вам точно определить, что доступно, и имеет несколько "безопасных" значений по умолчанию.
Ответ 3
Google App Engine с открытым исходным кодом SDK содержит подробную и прочную реализацию механики, чтобы остановить импорт нежелательных модулей (чтобы помочь обнаружить код, пытающийся импортировать модули, которые не доступны в производственных экземплярах App Engine), хотя даже это можно было бы подорвать, если код пользователя был злым, а не просто ошибочным (экземпляры производства, очевидно, имеют больше уровней защиты, например, просто не имея этих модулей вокруг вообще; -).
Итак, все зависит от того, насколько глубокой должна быть ваша защита. С одной стороны вы просто вставляете встроенный __import__
в другое место и заменяете его своей функцией, которая выполняет все проверки, которые вы хотите, прежде чем делегировать __builtin__
; возможно, 20 строк кода, 30 минут для полноценного тестирования и тестирования... но это может не защитить вас долго, если кто-то действительно предложит мне миллион долларов, чтобы проникнуть в вашу систему (и, предположительно, я не был хорошим, Конечно, две туфли - парень, я на самом деле AM.-). С другой стороны, вы развертываете глубокую серию уровней защиты, которые могут занимать тысячи строк и недель работы по внедрению и тестированию - учитывая такой бюджет ресурсов, я мог бы, несомненно, реализовать то, что я не смог бы проникнуть (но там всегда риск того, что кто-то ELSE умнее и более Python-подкованных, чем я, конечно!).
Итак, насколько глубоко вы хотите идти, или, вернее, насколько глубоко вы можете АФФОРД идти...?
Ответ 4
К сожалению, я думаю, что то, что вы пытаетесь сделать, принципиально невозможно. Если пользователи могут выполнять произвольный код в своем приложении, они могут делать все, что захотят. Даже если вы смогли помешать им импортировать определенные модули, ничто не помешало бы им самим писать эквивалентную функциональность (с нуля или с помощью некоторых доступных модулей).
Я не знаю специфики реализации песочницы в Python, но я мог бы представить себе что-то, что нужно сделать на уровне интерпретатора и далеко не просто!
Ответ 5
Вы можете перегрузить механизм импорта. Мы использовали это, чтобы иметь систему лицензирования для плагинов, вы можете легко иметь белый список/черный список имен модулей.
Ответ 6
8 лет, йиш, и никто не понял этого?:/
Вы можете переопределить оператор import
или aka __import__
.
Это всего лишь проверенный код scribble, потому что я не мог найти никакой законной ссылки:
import importlib
def secure_importer(name, globals=None, locals=None, fromlist=(), level=0):
if name != 'C': print(name, fromlist, level)
# not exactly a good verification layer
frommodule = globals['__name__'] if globals else None
if name == 'B' and frommodule != 'C':
raise ImportError("module '%s' is restricted."%name)
return importlib.__import__(name, globals, locals, fromlist, level)
__builtins__.__dict__['__import__'] = secure_importer
import C
и здесь тесты для этого кода:
Python 3.4.3 |Anaconda 2.3.0 (32-bit)| (default, Mar 6 2015, 12:08:17) [MSC v.1600 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>>
B ('f',) 0
imported secure module
>>> from B import f
B ('f',) 0
linecache None 0
encodings.utf_8 ['*'] 0
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
from B import f
File "\home\tcll\Projects\python\test\restricted imports\main.py", line 11, in secure_importer
raise ImportError("module '%s' is restricted."%name)
ImportError: module 'B' is restricted.
>>> import C
>>>
Пожалуйста, не комментируйте меня, используя Python34, у меня есть мои причины, и мой основной интерпретатор Linux специально для тестирования вещей (например, приведенного выше кода) для моего основного проекта.