
Безопасное выполнение кода
CodeJail управляет выполнением недоверенного кода в безопасных песочницах. Он предназначен в первую очередь для выполнения Python, но может использоваться и для других языков.
Безопасность обеспечивается с помощью AppArmor. Если ваша операционная система не поддерживает AppArmor или профиль AppArmor не определён и не настроен правильно, то CodeJail не обеспечит защиту выполнения.
CodeJail спроектирован как настраиваемый и автоматически сконфигурирует себя для выполнения Python, если вы установите его правильно.
Песочница CodeJail состоит из нескольких частей:
#) Среда песочницы. В случае Python это будет Python и связанные основные пакеты в виде virtualenv. Далее в этом документе она обозначается как . Эта среда доступна только для чтения и используется совместно всеми экземплярами песочниц.
Код в песочнице также имеет доступ к системным библиотекам в той степени, в которой это разрешает профиль AppArmor.
#) Рабочий каталог песочницы. Это эфемерный каталог, доступный только для чтения,
с именем вида /tmp/codejail-XXXXXXXX, содержащий представленный код
(./jailed_code), необязательные дополнительные файлы и доступный для записи
временный каталог (./tmp), который представленный код может использовать как
рабочую область.
Представленный код — это, как правило, код, отправленный студентом для проверки
на сервере, а дополнительные файлы — обычно python_lib.zip, содержащий
библиотеки для оценивания или служебные библиотеки.
Для работы CodeJail требуются две учётные записи. Одна учётная запись — основная,
под которой выполняется код и которая имеет доступ к созданию песочниц. Далее она
будет называться <SANDBOX_CALLER>. Вторая учётная запись — это учётная запись,
под которой работает песочница. Обычно это учётная запись sandbox.
В настоящее время библиотека протестирована на работу со следующими версиями
Python:
Ubuntu:
(Обратите внимание, что версия Python, используемая внутри песочницы, может отличаться от версии, используемой для самой библиотеки.)
Эти инструкции описывают, как настроить вашу операционную систему, чтобы
CodeJail мог безопасно выполнять код Python. Однако также можно установить
codejail.safe_exec.ALWAYS_BE_UNSAFE = True и выполнять представленный Python
напрямую на машине, без какой-либо безопасности. Это может быть приемлемо для
машин разработчиков, которых не беспокоит безопасность, и позволяет тестировать
интеграцию с API CodeJail. Однако его нельзя использовать, если любые входные
данные поступают из недоверенных источников. Не используйте этот вариант в
производственных системах.
Чтобы обеспечить безопасное выполнение Python, вам потребуется создать новый virtualenv. Это означает, что у вас будет два: основной virtualenv для вашего проекта и новый — для Python-кода в песочнице.
Выберите место для нового virtualenv и назовите его . Он будет
автоматически обнаружен и использован, если вы разместите его рядом с
существующим virtualenv, но с добавленным -sandbox. Так, если ваш
существующий virtualenv находится в /home/chris/ve/myproj, сделайте
равным /home/chris/ve/myproj-sandbox.
Пользователь, запускающий LMS, — это <SANDBOX_CALLER>, например, вы на своей
машине для разработки или www-data на сервере.
Прочие детали, зависящие от вашей конфигурации:
Создайте новый virtualenv, используя --copies, чтобы получить отдельный
исполняемый файл Python для ограничения::
$ sudo python3.12 -m venv --copies
По умолчанию virtualenv просто создаёт симлинк на системный Python, и конфигурация AppArmor по умолчанию в некоторых операционных системах может помешать применению ограничений к этому Python.
(Необязательно) Если у вас есть особые пакеты, которые должны быть доступны вашему коду в песочнице, установите их, активировав виртуальное окружение песочницы и используя pip для их установки::
$ /bin/pip install -r requirements/sandbox.txt
Добавьте пользователя песочницы::
$ sudo addgroup sandbox $ sudo adduser --disabled-login sandbox --ingroup sandbox
Разрешите веб-серверу запускать Python в песочнице от имени пользователя
sandbox. Создайте файл /etc/sudoers.d/01-sandbox::
$ sudo visudo -f /etc/sudoers.d/01-sandbox
<SANDBOX_CALLER> ALL=(sandbox) SETENV:NOPASSWD:/bin/python <SANDBOX_CALLER> ALL=(sandbox) SETENV:NOPASSWD:/usr/bin/find <SANDBOX_CALLER> ALL=(ALL) NOPASSWD:/usr/bin/pkill
(Обратите внимание, что бинарный файл find может выполнять произвольный
код, поэтому это небезопасный файл sudoers для целей, не связанных с CodeJail.)
Отредактируйте профиль AppArmor. Это текстовый файл, задающий ограничения для
исполняемого файла Python в песочнице. Файл должен находиться в
/etc/apparmor.d и должен быть назван по имени исполняемого файла, где
слэши заменены точками. Например, если ваш Python в песочнице находится в
/home/chris/ve/myproj-sandbox/bin/python, то ваш профиль AppArmor должен
быть /etc/apparmor.d/home.chris.ve.myproj-sandbox.bin.python.
Пример профиля см. в apparmor-profiles/. Профиль необходимо настроить
в соответствии с расположением вашей песочницы.
Загрузите профили::
$ sudo apparmor_parser --replace --warn=all --warn=no-debug-cache --Werror <APPARMOR_FILE>
Снова активируйте основной virtualenv вашего проекта.
Отключите использование PAM для установки rlimits::
sed -i '/pam_limits.so/d' /etc/pam.d/sudo
Если ваш CodeJail правильно настроен для использования safe_exec, попробуйте выполнить эти команды в терминале Python::
import codejail.jail_code
codejail.jail_code.configure('python', '<SANDENV>/bin/python', user='sandbox')
import codejail.safe_exec
jailed_globals = {}
codejail.safe_exec.safe_exec("output=open('/etc/passwd').read()", jailed_globals)
print(jailed_globals) # should be unreachable if codejail is working properly
Это должно завершиться ошибкой с исключением.
Если вам нужно изменить пакеты, установленные в virtualenv вашей песочницы, вам потребуется отключить AppArmor, поскольку ваш Python в песочнице не имеет прав на изменение файлов в своём каталоге site-packages.
Отключите AppArmor для вашей песочницы::
$ sudo apt-get install apparmor-utils # if you haven't already $ sudo aa-complain /etc/apparmor.d/home.chris.ve.myproj-sandbox.bin.python
Установите или иным образом измените установленные пакеты::
$ pip install -r requirements/sandbox.txt
Повторно включите AppArmor для вашей песочницы::
$ sudo aa-enforce /etc/apparmor.d/home.chris.ve.myproj-sandbox.bin.python
Для запуска тестов необходимо выполнить стандартные шаги установки. Затем необходимо задать следующие переменные окружения::
$ export CODEJAIL_TEST_USER=<owner of sandbox (usually 'sandbox')>
$ export CODEJAIL_TEST_VENV=<SANDENV>
Запустите тесты с помощью Makefile::
$ make tests
Некоторые прокси-тесты пропускаются, если не настроен прокси-режим.
CodeJail достаточно универсален, чтобы его можно было использовать в различных проектах для выполнения недоверенного кода. Он предоставляет два уровня:
jail_code.py обеспечивает безопасное выполнение подпроцессов. Это
достигается запуском программы в подпроцессе, управляемом AppArmor.
safe_exec.py обеспечивает специализированную обработку выполнения Python,
используя jail_code для предоставления семантики оператора exec в Python.