Перейти к содержимому
← Каталог php SSTI

SSTI: Twig createTemplate() Injection

Пользовательский ввод передаётся в Twig createTemplate(), что позволяет выполнить произвольный код на сервере.

mediumphpPro
Задача
# Server-Side Template Injection в Twig: от подстановки до RCE ## Сценарий Перед вами PHP-приложение интернет-магазина SecureShop. На странице профиля авторизованный пользователь может настроить персональное приветствие — поле «Bio Template». В интерфейсе явно указано, что поддерживается шаблонный синтаксис: пользователь может включить в bio подстановки своего имени, чтобы сообщение получалось живее. Сервер использует популярный для PHP шаблонизатор Twig (версия 3.x) и рендерит bio при каждом открытии профиля. С точки зрения разработчика всё выглядит логично — это же просто пользовательская кастомизация в фиксированном поле, набор переменных строго ограничен. Но обработчик профиля передаёт строку bio в шаблонизатор не как **данные**, а как **исходный код шаблона**: пользовательский ввод компилируется и исполняется как полноценная Twig-программа. А Twig — мощный язык: он умеет вычислять выражения, применять цепочки фильтров, работать с коллекциями и (что критично) запускать встроенные PHP-функции через специальные фильтры высшего порядка. Это значит, что любая Twig-конструкция, которую пользователь введёт в bio, будет интерпретирована шаблонизатором на сервере. Простая «персонализация приветствия» оказывается полноценным каналом для Server-Side Template Injection. А поскольку Twig в PHP-окружении имеет фильтры, принимающие callable-имена (имя PHP-функции в виде строки), от детектора SSTI до полноценного Remote Code Execution — буквально один шаг: применить фильтр к коллекции из одного элемента, передав имя нужной системной функции. ## Что мы тестируем Платформа определяет три уровня успешного исследования этой лабы: 1. **Обнаружение точки внедрения.** Найти в личном кабинете поле произвольного текста, которое рендерится как Twig-шаблон с подстановками. Для входа использовать стандартную тестовую учётную запись. 2. **Подтверждение SSTI.** Доказать, что сервер действительно интерпретирует значение поля как код шаблона, а не возвращает его «как есть». Стандартный детектор — арифметическое выражение, которое нормальный текст вернуть «вычисленным» не может. 3. **Эскалация SSTI → RCE → утечка флага.** От арифметического подтверждения перейти к выполнению произвольной PHP-функции через цепочку Twig-фильтров и прочитать переменную окружения процесса, содержащую CTF-флаг. ## Класс уязвимости Server-Side Template Injection возникает там, где пользовательский ввод используется как **код шаблона**, а не как **данные шаблона**. Разница принципиальна: данные передаются в заранее написанный шаблон через контекст и при выводе экранируются; код шаблона компилируется, и любые управляющие конструкции (выражения, фильтры, вызовы функций) исполняются. Для Twig типовая ошибка разработчика — вызов `createTemplate($userInput)`. Этот метод предназначен для динамических шаблонов в специальных сценариях (плагины, конструкторы писем), а не для пользовательского ввода. Любое выражение `{{ ... }}` в строке `$userInput` исполнится при `render()`. ## Цели | # | Цель | |---|------| | 1 | Войти в приложение под тестовой учётной записью и найти поле, которое позволяет настроить персональное приветствие | | 2 | Подтвердить SSTI через арифметическое выражение (детектор) | | 3 | Через цепочку Twig-фильтров вызвать встроенную PHP-функцию и получить значение переменной окружения с флагом | | 4 | Сдать полученный флаг формата `flag{...}` платформе | ## Данные | Параметр | Значение | |----------|----------| | Обычный пользователь | `demo` / `demo` | | Уязвимый функционал | Раздел профиля «Bio Template» | | Метод сохранения bio | `POST /profile/bio` (требует CSRF-токен из формы) | | Источник флага | Переменная окружения процесса приложения |
🚧 Сайт в разработке. Полный функционал пока недоступен. Все вопросы — support@hackandfix.ru