flawopen.com/SSTI/Jinja2
Безопасна ли функция Jinja2 render_template_string()?
Вызывайте render_template_string() только с исходным текстом шаблона, заданным кодом приложения. Если недоверенные данные вставляются в эту строку до разбора Jinja, возникает SSTI. В стандартном окружении Jinja во Flask без песочницы последствия могут включать выполнение кода — в зависимости от доступных объектов, конфигурации и самого приложения; это не происходит автоматически в каждом развёртывании.
# All four are the same bug render_template_string(f"Hi {name}") render_template_string("Hi " + name) render_template_string("Hi %s" % name) render_template_string("Hi {}".format(name)) # A very common real-world shape: @app.errorhandler(404) def not_found(e): return render_template_string( f"<h1>No such page: " f"{request.path}</h1>" ), 404 # The URL path is attacker-controlled.
# Template is a literal; the user value # arrives as a named context variable render_template_string( "Hi {{ name }}", name=name ) # Better still, a real template file render_template("greeting.html", name=name) # For the 404 case, no template # evaluation is needed at all: return render_template("404.html", path=request.path), 404
Чем опасен исходный текст шаблона под контролем атакующего
По умолчанию Flask предоставляет шаблонам глобальные объекты приложения, например config, request и session. Если атакующий контролирует исходный текст шаблона, Jinja вычисляет выражения с объектами, доступными в этом окружении. Последствия зависят от того, какие объекты и возможности открывает приложение. Безвредное арифметическое выражение может подтвердить факт вычисления, но само по себе не доказывает выполнение кода или доступность конкретных данных.
Шаблон может раскрыть чувствительные значения, если приложение поместило их в контекст. Например, config Flask может содержать SECRET_KEY или параметры базы данных, но конфигурации различаются. Не помещайте секреты в данные, доступные шаблонам, и не считайте экранирование вывода защитой от вычисления шаблона.
CVE-2024-56201 — отдельный случай
Эта уязвимость компилятора Jinja отличается от обычной SSTI и не является её обязательным условием: CVE-2024-56201 затрагивает Jinja 3.0.0–3.1.4, если атакующий может контролировать и содержимое, и имя шаблона. При таком условии было возможно выполнить произвольный код Python даже с включённой песочницей. Исправление вошло в Jinja 3.1.5. Изучите бюллетень и обновите библиотеку, если приложение принимает шаблоны или имена от атакующего.
Где это встречается
Такой шаблон кода встречается в обработчиках ошибок, выводящих запрошенный путь, административных функциях шаблонов писем, настройках оформления для клиентов и непредназначенных для публикации точках предварительного просмотра или отладки.
Частые вопросы
Нет. Автоэкранирование преобразует выведенные значения для снижения риска XSS. Оно не мешает компилировать пользовательскую строку как исходный текст шаблона. Эти меры относятся к разным этапам обработки.
В Jinja есть SandboxedEnvironment для пользовательских шаблонов, но документация предупреждает, что это не абсолютная защита. Передавайте только необходимые данные, избегайте объектов с побочными эффектами и ограничивайте CPU, память и процессы вне движка шаблонов. Песочница не делает безопасной подстановку недоверенных данных в шаблон до разбора.
Найдите вызовы render_template_string и проверьте, что первый аргумент — фиксированная строка, заданная приложением. Передавайте пользовательские значения как именованные переменные контекста или используйте файл шаблона. Также проверьте API динамической компиляции шаблонов и возможность задавать их имена.