Spec-Zone.ru › Python 2.7

rexec — Система ограниченного выполнения

Устарело начиная с версии 2.6: Модуль rexec был удалён в Python 3.

Изменено в версии 2.3: Модуль отключён.

Предупреждение

Документация оставлена для помощи в чтении старого кода, использующего этот модуль.

Этот модуль содержит класс RExec, который поддерживает r_eval(), r_execfile(), r_exec(), и r_import() методы, которые являются ограниченными версиями стандартных функций Python eval(), execfile() и операторов exec и import. Код, выполняемый в этой ограниченной среде, будет иметь доступ только к модулям и функциям, которые считаются безопасными; вы можете создать подкласс RExec, чтобы добавить или удалить возможности по желанию.

Предупреждение

Хотя модуль rexec разработан для работы, как описано ниже, у него есть несколько известных уязвимостей, которые могут быть использованы тщательно написанным кодом. Поэтому его не следует использовать в ситуациях, требующих «готовых к производству» мер безопасности. В таких ситуациях может потребоваться выполнение через дочерние процессы или очень тщательное «очищение» как кода, так и данных, подлежащих обработке. Альтернативно, будут приветствоваться предложения по исправлению известных уязвимостей модуля rexec.

Примечание

Класс RExec может предотвратить выполнение кода небезопасных операций, таких как чтение или запись файлов на диске или использование сокетов TCP/IP. Однако он не защищает от кода, использующего чрезвычайно большое количество памяти или времени процессора.

class rexec.RExec([hooks[, verbose]])

Возвращает экземпляр класса RExec.

hooks — экземпляр класса RHooks или его подкласс. Если он опущен или None, создаётся экземпляр по умолчанию класса RHooks. Всякий раз, когда модуль rexec ищет модуль (даже встроенный) или читает код модуля, он не обращается непосредственно к файловой системе. Вместо этого он вызывает методы экземпляра RHooks, который был передан или создан его конструктором. (На самом деле, объект RExec не делает эти вызовы — их делает объект загрузчика модулей, который является частью объекта RExec. Это позволяет ещё большую гибкость, что может быть полезно при изменении механики import в ограниченной среде.)

Предоставляя альтернативный объект RHooks, мы можем контролировать доступ к файловой системе для импорта модуля, не изменяя фактический алгоритм, который управляет порядком этих обращений. Например, мы могли бы заменить объект RHooks, который передает все запросы к файловой системе на удаленный файловый сервер по какому-либо механизму RPC, например, ILU. Загрузчик апплетов Grail использует это для поддержки импорта апплетов из URL-адреса для каталога.

Если verbose имеет значение true, дополнительный отладочный вывод может быть отправлен в стандартный вывод.

Важно понимать, что код, работающий в ограниченной среде, всё ещё может вызывать функцию sys.exit(). Чтобы запретить ограниченному коду завершать интерпретатор, всегда защищайте вызовы, которые вызывают выполнение ограниченного кода, оператором try/except, который перехватывает исключение SystemExit. Удаление функции sys.exit() из ограниченной среды недостаточно — ограниченный код всё равно мог бы использовать raise SystemExit. Удаление SystemExit — не разумный вариант; некоторые библиотечные коды используют это и сломались бы, если бы оно не было доступно.

См. также

Grail Home Page

Grail — это веб-браузер, написанный полностью на Python. Он использует модуль rexec в качестве основы для поддержки Python-апплетов и может служить примером использования этого модуля.

1. Объекты RExec

Экземпляры RExec поддерживают следующие методы:

RExec.r_eval(code)

code должен быть либо строкой, содержащей выражение Python, либо скомпилированным объектом кода, который будет вычислен в модуле __main__ ограниченной среды. Значение выражения или объекта кода будет возвращено.

RExec.r_exec(code)

code должен быть либо строкой, содержащей одну или несколько строк Python-кода, либо скомпилированным объектом кода, который будет выполнен в модуле __main__ ограниченной среды.

RExec.r_execfile(filename)

Выполнить Python-код, содержащийся в файле filename, в модуле __main__ ограниченной среды.

Методы, имена которых начинаются с s_, аналогичны функциям, начинающимся с r_, но код получит доступ к ограниченным версиям стандартных потоков ввода-вывода sys.stdin, sys.stderr, и sys.stdout.

RExec.s_eval(code)

code должен быть строкой, содержащей выражение Python, которое будет вычислено в ограниченной среде.

RExec.s_exec(code)

code должен быть строкой, содержащей одну или несколько строк Python-кода, которые будут выполнены в ограниченной среде.

RExec.s_execfile(code)

Выполнить Python-код, содержащийся в файле filename, в ограниченной среде.

Объекты RExec также должны поддерживать различные методы, которые будут неявно вызываться кодом, выполняющимся в ограниченной среде. Переопределение этих методов в подклассе используется для изменения политик, навязанных ограниченной средой.

RExec.r_import(modulename[, globals[, locals[, fromlist]]])

Импортирует модуль modulename, вызывая исключение ImportError, если модуль считается небезопасным.

RExec.r_open(filename[, mode[, bufsize]])

Метод, вызываемый при вызове open() в ограниченной среде. Аргументы идентичны аргументам open(), и должен быть возвращён объект файла (или экземпляр класса, совместимый с объектами файлов). По умолчанию RExec разрешает открытие любого файла для чтения, но запрещает любые попытки записи в файл. См. пример ниже для реализации менее ограниченного r_open().

RExec.r_reload(module)

Перезагрузить объект модуля module, повторно проанализировав и инициализировав его.

RExec.r_unload(module)

Выгрузить объект модуля module (удалить его из словаря sys.modules ограниченной среды).

И их эквиваленты с доступом к ограниченным стандартным потокам ввода-вывода:

RExec.s_import(modulename[, globals[, locals[, fromlist]]])

Импортирует модуль modulename, вызывая исключение ImportError, если модуль считается небезопасным.

RExec.s_reload(module)

Перезагрузить объект модуля module, повторно проанализировав и инициализировав его.

RExec.s_unload(module)

Выгрузить объект модуля module.

2. Определение ограниченных сред

Класс RExec имеет следующие атрибуты класса, которые используются методом __init__(). Изменение этих атрибутов в существующем экземпляре не повлияет на него; вместо этого создайте подкласс RExec и присвойте новые значения в определении класса. Экземпляры нового класса затем будут использовать эти новые значения. Все эти атрибуты являются кортежами строк.

RExec.nok_builtin_names

Содержит имена встроенных функций, которые не будут доступны программам, выполняющимся в ограниченной среде. Значение для RExec равно ('open', 'reload', '__import__'). (Это предоставляет исключения, поскольку подавляющее большинство встроенных функций безвредны. Подкласс, который хочет переопределить эту переменную, должен, вероятно, начать с значения базового класса и добавить дополнительные запрещенные функции — когда к Python добавляются новые опасные встроенные функции, они также будут добавлены в этот модуль.)

RExec.ok_builtin_modules

Содержит имена встроенных модулей, которые можно безопасно импортировать. Значение для RExec равно ('audioop', 'array', 'binascii', 'cmath', 'errno', 'imageop', 'marshal', 'math', 'md5', 'operator', 'parser', 'regex', 'select', 'sha', '_sre', 'strop', 'struct', 'time'). Аналогичное замечание о переопределении этой переменной применимо — используйте значение из базового класса в качестве отправной точки.

RExec.ok_path

Содержит каталоги, которые будут проверяться при выполнении import в ограниченной среде. Значение для RExec такое же, как sys.path (на момент загрузки модуля) для неограниченного кода.

RExec.ok_posix_names

Содержит имена функций в модуле os, которые будут доступны программам, выполняющимся в ограниченной среде. Значение для RExec равно ('error', 'fstat', 'listdir', 'lstat', 'readlink', 'stat', 'times', 'uname', 'getpid', 'getppid', 'getcwd', 'getuid', 'getgid', 'geteuid', 'getegid').

RExec.ok_sys_names

Содержит имена функций и переменных в модуле sys, которые будут доступны программам, выполняющимся в ограниченной среде. Значение для RExec равно ('ps1', 'ps2', 'copyright', 'version', 'platform', 'exit', 'maxint').

RExec.ok_file_types

Содержит типы файлов, из которых разрешается загружать модули. Каждый тип файла — целочисленная константа, определённая в модуле imp. Значимые значения — PY_SOURCE, PY_COMPILED, и C_EXTENSION. Значение для RExec равно (C_EXTENSION, PY_SOURCE). Добавление PY_COMPILED в подклассы не рекомендуется; злоумышленник может выйти из режима ограниченного выполнения, поместив сгенерированный файл (.pyc) в любой каталог вашей файловой системы, например, записав его в /tmp или загрузив в директорию /incoming вашего публичного FTP-сервера.

3. Пример

Предположим, что мы хотим немного более либеральную политику, чем стандартный класс RExec. Например, если мы готовы разрешить запись файлов в /tmp, мы можем создать подкласс класса RExec:

class TmpWriterRExec(rexec.RExec):
    def r_open(self, file, mode='r', buf=-1):
        if mode in ('r', 'rb'):
            pass
        elif mode in ('w', 'wb', 'a', 'ab'):
            # check filename: must begin with /tmp/
            if file[:5]!='/tmp/':
                raise IOError("can't write outside /tmp")
            elif (string.find(file, '/../') >= 0 or
                 file[:3] == '../' or file[-3:] == '/..'):
                raise IOError("'..' in filename forbidden")
        else: raise IOError("Illegal open() mode")
        return open(file, mode, buf)

Обратите внимание, что вышеприведённый код иногда будет запрещать совершенно допустимое имя файла; например, код в ограниченной среде не сможет открыть файл с именем /tmp/foo/../bar. Для исправления этого метод r_open() должен упростить имя файла до /tmp/bar, что потребует разделения имени файла и выполнения различных операций с ним. В случаях, когда безопасность имеет первостепенное значение, предпочтительнее написать простой код, который иногда является чрезмерно ограниченным, вместо более общего кода, который также сложнее и может содержать скрытую уязвимость.

© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/2.7/library/rexec.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API