У меня есть проект, в котором мне нужно разрешить пользователям запускать произвольный ненадежный код Python ( примерно так ) на моем сервере. Я довольно новичок в python, и я хотел бы избежать ошибок, которые могут привести к дырам в системе безопасности или другим уязвимостям в системе. Существуют ли передовые практики, рекомендуемые материалы для чтения или другие советы, которые вы можете дать мне, чтобы сделать мой сервис пригодным для использования, но не используемым?
Вот что я рассмотрел до сих пор:
- Удалить
__builtins__
изexec
контекста, чтобы запретить использование потенциально опасных пакетов, таких какos
. Пользователи смогут использовать только те пакеты, которые я им предоставляю. - Используйте потоки для обеспечения разумного времени ожидания.
- Я хотел бы ограничить общий объем памяти, который может быть выделен в
exec
контексте, но я не уверен, возможно ли это вообще.
Есть несколько альтернатив стриту exec
, но я не уверен, какой из них будет полезен здесь:
- Использование для обнаружения
ast.NodeVisitor
любых попыток доступа к небезопасным объектам. Но какие объекты я должен запрещать? - Поиск любых двойных подчеркиваний на входе. (менее изящный, чем вышеуказанный вариант).
- Использование
PyPy
или что-то похожее на песочницу кода.
ПРИМЕЧАНИЕ. Мне известно, что существует хотя бы один интерпретатор на основе JavaScript. Это не будет работать в моем сценарии.
Ответы:
Песочница на Python это сложно . Python по своей сути интроспективен на нескольких уровнях.
Это также означает, что вы можете найти фабричные методы для конкретных типов из самих этих типов и создать новые низкоуровневые объекты, которые будут выполняться интерпретатором напрямую без ограничений.
Вот несколько примеров поиска творческих способов вырваться из песочниц Python:
Нед Бэтчелдер начинает с демонстрации того, насколько опасен на
eval()
самом деле ;eval()
часто используется для выполнения выражений Python; как примитивная и наивная песочница для однострочников.Затем он продолжил пытаться применить те же принципы к Python 3 , в конечном итоге преуспев в достижении некоторых полезных указателей.
Пьер Бурдон использует аналогичные методы, чтобы взломать систему Python на взломать
Основная идея всегда состоит в том, чтобы найти способ создания базовых типов Python; функции и классы и вырваться из оболочки, заставив интерпретатор Python выполнить произвольный (непроверенный!) байт-код.
То же самое и более относится к
exec
утверждению (exec()
функция в Python 3).Итак, вы хотите:
Строго контролируйте байтовую компиляцию кода Python или, по крайней мере, постобработайте байт-код, чтобы исключить любой доступ к именам, начинающимся с подчеркиваний.
Это требует глубоких знаний о том, как работает интерпретатор Python и как структурирован байт-код Python. Объекты кода являются вложенными; Байт-код модуля охватывает только верхний уровень операторов, каждая функция и класс состоят из собственной последовательности байт-кода плюс метаданные, содержащие, например, другие объекты байт-кода для вложенных функций и классов.
Вам необходимо внести в белый список модули, которые можно использовать. Осторожно.
Модуль Python содержит ссылки на другие модули. Если вы импортируете
os
,os
в вашем пространстве имен модуля будет находиться локальное имя, которое относится кos
модулю. Это может привести решительного злоумышленника к модулям, которые могут помочь им вырваться из песочницы.pickle
Модуль, например, позволяет загружать произвольные объекты кода, например, так что если какой - либо путь через белый список модулей приводит кpickle
модулю, то есть проблема до сих пор.Вам необходимо строго ограничить временные квоты. Даже самый стерилизованный код может работать вечно, связывая ваши ресурсы.
Взгляните на RestrictedPython , который пытается дать вам строгий контроль байт-кода.
RestrictedPython
превращает код Python во что-то, что позволяет вам контролировать, какие имена, модули и объекты допустимы в Python с 2.3 по 2.7.Если
RestrictedPython
это достаточно безопасно для ваших целей, зависит от политики, которую вы реализуете. Запрет доступа к именам, начинающимся с подчеркивания и строго внесения в белый список модулей, будет началом.По моему мнению, единственный действительно надежный вариант - это использовать отдельную виртуальную машину, которая не имеет доступа к сети во внешний мир, который вы уничтожаете после каждого запуска. Каждый новый скрипт получает новую виртуальную машину. Таким образом, даже если коду удастся вырваться из вашей изолированной программной среды Python (что не исключено), весь доступ к злоумышленнику будет кратковременным и бесполезным.
источник
TL; DR Используйте chroot / jail и запускайте как пользовательский пользователь без каких-либо привилегий.
Лучшая практика для выполнения ненадежного кода - отделить его через системную песочницу. Для большей безопасности:
Вы также следуете стандартным методам безопасного запуска вещей в chroot. Вы можете перестраивать файловую систему chroot при каждом вызове, особенно параноидально. Обычно вы просто лишаете пользователя возможности вносить изменения в файловую систему, в которой запускается chroot.
источник
Вы не можете сделать это безопасно.
Если вы хотите сделать что-то подобное безопасно, вы должны начать с собственной реализации python, которая работает в полностью контролируемой среде, предпочтительно в браузере пользователя, а не в вашей системе. Вы можете начать с Jython (python для Java) и упаковать его как Java-апплет. Поскольку он будет работать в изолированной программной среде java на компьютере пользователя, ваша система будет достаточно безопасной.
источник
Как сказал выше Мартейн, это действительно очень сложно в Python. Прямо потому, что Python настолько интроспективен, я не думаю, что это возможно, ограничивая возможности языка. И если вы получите песочницу, работающую для одной версии Python, есть вероятность, что следующая версия сломает ее.
Я бы посмотрел на PyPy вместо стандартного CPython. Короче говоря, это совместимая альтернативная реализация Python. Он имеет несколько преимуществ и различных функций, и одним из них является песочница путем замены системных вызовов вместо ограничения языковых функций.
источник
Пока производительность не очень важна для вас, вы всегда можете запустить ее в Brython, которая эффективно помещает ее в песочницу JavaScript
источник