Песочница
Песочница Jinja2 может быть использована для оценки небезопасного кода. Доступ к небезопасным атрибутам и методам запрещён.
Предполагая, что env является SandboxedEnvironment в конфигурации по умолчанию, следующий фрагмент кода демонстрирует, как это работает:
>>> env.from_string("{{ func.func_code }}").render(func=lambda:None)
u''
>>> env.from_string("{{ func.func_code.do_something }}").render(func=lambda:None)
Traceback (most recent call last):
...
SecurityError: access to attribute 'func_code' of 'function' object is unsafe.
API
-
class jinja2.sandbox.SandboxedEnvironment([options]) -
Песочница для окружения. Она работает как обычное окружение, но сообщает компилятору сгенерировать песочницу для кода. Кроме того, подклассы этого окружения могут переопределять методы, которые сообщают исполняемой среде, какие атрибуты или функции безопасно использовать.
Если шаблон пытается получить доступ к небезопасному коду, вызывается
SecurityError. Однако могут возникнуть и другие исключения во время рендеринга, поэтому вызывающая сторона должна убедиться, что все исключения обрабатываются.-
call_binop(context, operator, left, right) -
Для перехваченных бинарных операторов (
intercepted_binops()) эта функция выполняется вместо встроенного оператора. Это можно использовать для настройки поведения определённых операторов.Changelog
Новая в версии 2.6.
-
call_unop(context, operator, arg) -
Для перехваченных унарных операторов (
intercepted_unops()) эта функция выполняется вместо встроенного оператора. Это можно использовать для настройки поведения определённых операторов.Changelog
Новая в версии 2.6.
-
default_binop_table = {'%': <built-in function mod>, '*': <built-in function mul>, '**': <built-in function pow>, '+': <built-in function add>, '-': <built-in function sub>, '/': <built-in function truediv>, '//': <built-in function floordiv>} -
Таблицу обратного вызова по умолчанию для бинарных операторов. Копия этой таблицы доступна в каждом экземпляре песочницы, как
binop_table
-
default_unop_table = {'+': <built-in function pos>, '-': <built-in function neg>} -
Таблица обратного вызова по умолчанию для унарных операторов. Копия этой таблицы доступна в каждом экземпляре песочницы, как
unop_table
-
intercepted_binops = frozenset({}) -
набор бинарных операторов, которые должны быть перехвачены. Каждый оператор, добавленный в этот набор (пустой по умолчанию), делегируется методу
call_binop(), который выполнит операцию. Обратный вызов оператора по умолчанию задан значениемbinop_tableСледующие бинарные операторы могут быть перехвачены:
//,%,+,*,-,/, и**По умолчанию операция из таблицы операторов соответствует встроенной функции. Перехваченные вызовы всегда медленнее, чем вызовы с использованием операторов, поэтому убедитесь, что вы перехватываете только нужные вам операторы.
Changelog
Новая в версии 2.6.
-
intercepted_unops = frozenset({}) -
набор унарных операторов, которые должны быть перехвачены. Каждый оператор, добавленный в этот набор (пустой по умолчанию), делегируется методу
call_unop(), который выполнит операцию. Обратный вызов оператора по умолчанию задан значениемunop_tableСледующие унарные операторы могут быть перехвачены:
+,-По умолчанию операция из таблицы операторов соответствует встроенной функции. Перехваченные вызовы всегда медленнее, чем вызовы с использованием операторов, поэтому убедитесь, что вы перехватываете только нужные вам операторы.
Changelog
Новая в версии 2.6.
-
is_safe_attribute(obj, attr, value) -
Окружение песочницы вызовет этот метод для проверки, является ли атрибут объекта безопасным для доступа. По умолчанию все атрибуты, начинающиеся с символа подчёркивания, считаются закрытыми, а также специальные атрибуты внутренних объектов Python, возвращаемые функцией
is_internal_attribute().
-
is_safe_callable(obj) -
Проверяет, является ли объект безопасным для вызова. По умолчанию функция считается безопасной, если атрибут
unsafe_callableсуществует и равен True. Переопределите этот метод, чтобы изменить поведение, но это не повлияет на декораторunsafeиз этого модуля.
-
-
class jinja2.sandbox.ImmutableSandboxedEnvironment([options]) -
Работает точно так же, как обычная
SandboxedEnvironment, но не допускает модификаций встроенных изменяемых объектовlist,set, иdictс помощью функцииmodifies_known_mutable().
-
exception jinja2.sandbox.SecurityError(message=None) -
Вызывается, если шаблон пытается выполнить небезопасное действие, если включён режим песочницы.
-
jinja2.sandbox.unsafe(f) -
Отмечает функцию или метод как небезопасный.
@unsafe def delete(self): pass
-
jinja2.sandbox.is_internal_attribute(obj, attr) -
Проверяет, является ли заданный атрибут внутренним атрибутом Python. Например, эта функция возвращает
Trueдля атрибутаfunc_codeобъектов Python. Это полезно, если переопределён метод средыis_safe_attribute().>>> from jinja2.sandbox import is_internal_attribute >>> is_internal_attribute(str, "mro") True >>> is_internal_attribute(str, "upper") False
-
jinja2.sandbox.modifies_known_mutable(obj, attr) -
Эта функция проверяет, будет ли вызов атрибута встроенного изменяемого объекта (список, словарь, множество или очередь с двойной стороной) изменять его. Она также поддерживает "пользовательские" версии объектов (
sets.Set,UserDict.*и т. д.) и с Python 2.6 и выше — абстрактные базовые классыMutableSet,MutableMapping, иMutableSequence.>>> modifies_known_mutable({}, "clear") True >>> modifies_known_mutable({}, "keys") False >>> modifies_known_mutable([], "append") True >>> modifies_known_mutable([], "index") FalseЕсли вызов осуществляется с недопустимым объектом (например, unicode), возвращается
False.>>> modifies_known_mutable("foo", "upper") False
Примечание
Песочница Jinja2 сама по себе не является решением для абсолютной безопасности. Особенно для веб-приложений необходимо учитывать, что пользователи могут создавать шаблоны с произвольным HTML, поэтому крайне важно гарантировать, что (если на одном сервере работают несколько пользователей) они не смогут навредить друг другу с помощью вставок JavaScript и т. д.
Также песочница эффективна только в соответствии с настройками. Мы настоятельно рекомендуем передавать шаблонам только неразделяемые ресурсы и использовать какой-либо вид белого списка для атрибутов.
Также следует помнить, что шаблоны могут генерировать ошибки во время выполнения или компиляции, поэтому необходимо перехватывать их.
Перехват операторов
Изменения
Введено в версии 2.6.
Для максимальной производительности Jinja2 позволяет операторам непосредственно вызывать методы, специфичные для типа. Это означает, что перехват с помощью переопределения Environment.call() невозможен. Кроме того, преобразование оператора в специальный метод не всегда возможно напрямую из-за принципов работы операторов. Например, для деления существует не один специальный метод.
С Jinja 2.6 появилась поддержка явного перехвата операторов. Это позволяет настраивать определённые операторы по мере необходимости. Чтобы перехватить оператор, необходимо переопределить атрибут SandboxedEnvironment.intercepted_binops. После добавления необходимого оператора в этот набор Jinja2 сгенерирует байт-код, вызывающий функцию SandboxedEnvironment.call_binop(). Для унарных операторов необходимо использовать атрибуты и методы unary вместо них.
В реализации по умолчанию SandboxedEnvironment.call_binop используется SandboxedEnvironment.binop_table для преобразования символов операторов в обратные вызовы, выполняющие поведение операторов по умолчанию.
Этот пример показывает, как можно отключить оператор «степень» (**) в Jinja2:
from jinja2.sandbox import SandboxedEnvironment
class MyEnvironment(SandboxedEnvironment):
intercepted_binops = frozenset(['**'])
def call_binop(self, context, operator, left, right):
if operator == '**':
return self.undefined('the power operator is unavailable')
return SandboxedEnvironment.call_binop(self, context,
operator, left, right)
Убедитесь, что вы всегда вызываете метод супер, даже если вы не перехватываете вызов. Jinja2 может внутренне вызвать метод для оценки выражений.
© 2007–2020 Pallets
Licensed under the BSD 3-clause License.
https://jinja.palletsprojects.com/en/2.10.x/sandbox/