Лучшие практики для выполнения ненадежного кода

31

У меня есть проект, в котором мне нужно разрешить пользователям запускать произвольный ненадежный код Python ( примерно так ) на моем сервере. Я довольно новичок в python, и я хотел бы избежать ошибок, которые могут привести к дырам в системе безопасности или другим уязвимостям в системе. Существуют ли передовые практики, рекомендуемые материалы для чтения или другие советы, которые вы можете дать мне, чтобы сделать мой сервис пригодным для использования, но не используемым?

Вот что я рассмотрел до сих пор:

  • Удалить __builtins__из execконтекста, чтобы запретить использование потенциально опасных пакетов, таких как os. Пользователи смогут использовать только те пакеты, которые я им предоставляю.
  • Используйте потоки для обеспечения разумного времени ожидания.
  • Я хотел бы ограничить общий объем памяти, который может быть выделен в execконтексте, но я не уверен, возможно ли это вообще.

Есть несколько альтернатив стриту exec, но я не уверен, какой из них будет полезен здесь:

  • Использование для обнаружения ast.NodeVisitorлюбых попыток доступа к небезопасным объектам. Но какие объекты я должен запрещать?
  • Поиск любых двойных подчеркиваний на входе. (менее изящный, чем вышеуказанный вариант).
  • Использование PyPyили что-то похожее на песочницу кода.

ПРИМЕЧАНИЕ. Мне известно, что существует хотя бы один интерпретатор на основе JavaScript. Это не будет работать в моем сценарии.

PSWG
источник
8
Некоторые отправные точки для изучения: blog.delroth.net/2013/03/… , nedbatchelder.com/blog/201206/eval_really_is_dangerous.html , nedbatchelder.com/blog/201302/… и nedbatchelder.com/blog/201302/finding_python_3_builtins. HTML о взломе песочниц.
Мартин Питерс
3
@MartijnPieters: Отлично. Вероятно, заслуживает ответа, если вы суммируете каждый из них.
Роберт Харви
Учитывайте также: мусор, оставленный на диске, сеть (не позволяйте им рассылать спам или что-либо еще), права доступа к другим файлам (чтение ваших файлов). Даже извлечение в цикле while может разрушить механику CD ... Я бы пошел на виртуализацию (джейлы или какой-нибудь kvm, как вы это называете) или, по крайней мере, на пользователя, почти не имеющий привилегий. Установите разумное количество и объем памяти, чтобы использовать ваши собственные программы.
kyticka
1
Попробуйте PyPy :> Песочница: PyPy позволяет запускать ненадежный код полностью безопасным способом.
Vorac

Ответы:

28

Песочница на 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 (что не исключено), весь доступ к злоумышленнику будет кратковременным и бесполезным.

Мартейн Питерс
источник
10

TL; DR Используйте chroot / jail и запускайте как пользовательский пользователь без каких-либо привилегий.

Лучшая практика для выполнения ненадежного кода - отделить его через системную песочницу. Для большей безопасности:

  • создать контейнер только с Python и его зависимостями и зависимостями контейнера
  • создать контейнер без всех устройств, которые не являются абсолютно необходимыми (например, сеть и хранилище)
  • создать контейнер с ограничениями на использование памяти и процесса
  • пересоздавать контейнер при каждом запуске (или, по крайней мере, при каждом уникальном пользователе и максимальном периоде времени)
  • работать как пользователь с наименьшими необходимыми привилегиями
  • работать как пользователь, у которого нет прав на запись файлов

Вы также следуете стандартным методам безопасного запуска вещей в chroot. Вы можете перестраивать файловую систему chroot при каждом вызове, особенно параноидально. Обычно вы просто лишаете пользователя возможности вносить изменения в файловую систему, в которой запускается chroot.

dietbuddha
источник
Это единственная вещь, где вы будете хотя бы отдаленно уверены, что поняли это правильно - дайте этому свой собственный процесс.
Майкл Кохн
3

Вы не можете сделать это безопасно.

Если вы хотите сделать что-то подобное безопасно, вы должны начать с собственной реализации python, которая работает в полностью контролируемой среде, предпочтительно в браузере пользователя, а не в вашей системе. Вы можете начать с Jython (python для Java) и упаковать его как Java-апплет. Поскольку он будет работать в изолированной программной среде java на компьютере пользователя, ваша система будет достаточно безопасной.

ddyer
источник
4
Вопрос безопасности был для его сервера, а не для компьютера клиента. Потенциальные угрозы безопасности Java, как и любые другие веб-технологии, заключаются в том, что сервер может использоваться для развертывания программ, опасных для клиента.
ddyer
1
@grasGendarme очень похожи на новые истории о авиакатастрофах, которые на самом деле многое говорят о том, насколько они редки; Истории о дырах в безопасности Java говорят о том, что Java относительно безопасна. Вы никогда не получите такую ​​историю о C, потому что ответ, который вы получите, будет «ну, ну, если вы запустите его, он сделает все, что захочет»
Ричард Тингл,
2

Как сказал выше Мартейн, это действительно очень сложно в Python. Прямо потому, что Python настолько интроспективен, я не думаю, что это возможно, ограничивая возможности языка. И если вы получите песочницу, работающую для одной версии Python, есть вероятность, что следующая версия сломает ее.

Я бы посмотрел на PyPy вместо стандартного CPython. Короче говоря, это совместимая альтернативная реализация Python. Он имеет несколько преимуществ и различных функций, и одним из них является песочница путем замены системных вызовов вместо ограничения языковых функций.

Джеймс
источник
0

Пока производительность не очень важна для вас, вы всегда можете запустить ее в Brython, которая эффективно помещает ее в песочницу JavaScript

Большой Ян
источник