STTI

NOTE

SSTI (Server-Side Template Injection)

Basics

SSTI occurs when an application embeds user input directly into a Template Engine (like Jinja2, Twig, or Mako) instead of passing it as data. Template engines are designed to execute code to generate dynamic HTML; if you can inject into them, you aren’t just changing text—you are running code on the server.

What to look for

A simple SSTI test is mathematical evaluation: send an expression in the template syntax and check whether the server renders its result.

The Test:

  1. Input: {{7*7}} or ${7*7}
  2. Result: If the page renders 49, you have confirmed SSTI.
  3. The Fingerprint: Try different syntaxes to see which engine is running:
    • ${7*7} -> ${7*7} (No change? Try {{7*7}})
    • {{7*'7'}} -> 7777777 (Likely Jinja2 or Twig)
    • {{7*'7'}} -> 49 (Likely Mako)

Common template engines

  1. Jinja2 (Python/Flask/Django):
    • Syntax: {{ ... }}
    • Exploit Goal: Access the __mro__ or __subclasses__ to find the os module and run system commands.
  2. Twig (PHP/Symfony):
    • Syntax: {{ ... }}
    • Exploit Goal: Use the _self or registerUndefinedFilterCallback to execute exec() or system().
  3. Java (Thymeleaf/FreeMarker):
    • Syntax: ${ ... }
    • Exploit Goal: Use Java Reflection to access java.lang.Runtime for RCE.

Testing workflow

  • Step 1: Identify the Engine
  • Step 2: Read Local Files
    • Jinja2 Example: {{ get_flashed_messages.__shell__.open('/etc/passwd').read() }}
  • Step 3: Gain RCE (Remote Code Execution)
    • Jinja2 (Standard): {{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}
    • Twig: {{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id")}}

References

  • PayloadsAllTheThings - SSTI: The most comprehensive list of payloads for every engine (Python, PHP, Java, Ruby).
  • HackTricks - SSTI: Reference material for identifying template engines and their behavior.
  • Tplmap: The “SQLmap” of SSTI. Warning: Use cautiously in OSCP (check current exam rules on automated exploitation tools).

Scope note

If you see {{ ... }} and your math doesn’t work, check for Client-Side Template Injection (CSTI). If the site uses AngularJS or Vue.js, the “math” might only work in your browser, not on the server. In that case, treat it like XSS, not RCE.