flawopen.com/SSTI/Объяснение
Что такое серверная инъекция в шаблон?
Серверная инъекция в шаблон возникает, когда недоверенный ввод интерпретируется как исходный код шаблона, а не передаётся как данные. Последствия зависят от движка, конфигурации и доступных возможностей: от вычисления выражений до выполнения кода на сервере. Не всякая SSTI приводит к выполнению кода.
# Python / Jinja2 template = f"Hello {name}!" return render_template_string(template) # Input: {{ 7*7 }} renders as "49" # This confirms expression evaluation; # impact still depends on engine access. // Java / Freemarker String tpl = "Welcome " + userName; new Template("t", tpl, cfg) .process(model, out);
# The template is a fixed string the # developer wrote. The user value is # passed in as a variable. return render_template( "greeting.html", name=name ) # Or with a literal template string: return render_template_string( "Hello {{ name }}!", name=name ) // Java equivalent: template from file, // user value in the model map.
Ключевое различие
У любого шаблонизатора два вида входных данных: сам шаблон и данные контекста. Шаблон — это программа, а данные — значения, которые она читает. SSTI возникает, когда пользовательскому вводу позволяют перейти из категории данных в исходный код шаблона.
Это та же структурная ошибка, что и SQL-инъекция, при которой данные объединяют с текстом запроса, и Log4Shell, где данные попадали в вычислитель выражений через сообщение журнала. Исправление основано на одном принципе: программа остаётся неизменной, а недоверенные значения передаются отдельным каналом параметров.
Когда последствия могут включать выполнение кода
Если движок предоставляет шаблону мощные объекты или методы, атакующий может получить доступ к чувствительным возможностям приложения. Возможность выполнения кода зависит от движка, версии, конфигурации, песочницы и модели данных. Другие последствия — раскрытие данных и исчерпание ресурсов. Считайте управляемый пользователем исходный код шаблона активной логикой; не полагайтесь только на песочницу без ограничения доступных объектов и ресурсов рендеринга.
Как обнаружить
{{7*7}}
${7*7}
<%= 7*7 %>
#{7*7}
Если ответ содержит 49 вместо исходного текста, ввод вычисляется как синтаксис шаблона. Такие короткие арифметические проверки помогают выявить вычисление в разрешённой тестовой среде; синтаксис различается, поэтому сам по себе не позволяет надёжно определить движок.
Часто задаваемые вопросы
Нет. Клиентская инъекция в шаблон выполняется в браузере жертвы и может быть разновидностью XSS. SSTI вычисляется на сервере внутри процесса приложения. Последствия зависят от движка и доступных возможностей; некоторые конфигурации допускают выполнение кода на сервере, но это не происходит автоматически при любой SSTI.
Нет. Автоэкранирование обрабатывает выводимые значения, но не мешает разобрать значение как синтаксис шаблона. Оно помогает против XSS в выводе, но не против внедрения в исходный текст шаблона.
Считайте переданный пользователем исходный код шаблона исполняемой логикой и по умолчанию не обрабатывайте его в основном контексте приложения. Если такая функция необходима, используйте движок для ограниченных шаблонов, предоставляйте минимум инертных данных и ограничивайте CPU, память, размер вывода и время. Песочница снижает доступ, но сама по себе не является полной границей безопасности.
Источники
- CWE-1336 — Improper Neutralization of Special Elements Used in a Template Engine
- PortSwigger Web Security Academy — server-side template injection
- OWASP Testing Guide — testing for SSTI
- Is Jinja2's render_template_string() safe?
- Are Freemarker and Velocity templates safe with user input?
- Jinja documentation — Sandbox security considerations