Problem Framing
Server-Side Template Injection (SSTI) is a critical web application vulnerability that arises when an attacker can inject malicious code into a server-side template. This code is then processed and executed by the template engine on the server, potentially leading to remote code execution (RCE), information disclosure, denial-of-service, or other severe security compromises [1][2][3][4][5][6][7][8][9][10].
Unlike client-side injection vulnerabilities like Cross-Site Scripting (XSS), which target the user's browser, SSTI directly attacks the server itself. The impact can be profound, granting attackers a foothold within the application's environment, access to sensitive data, and the ability to compromise the entire system [2][3][4].
Template engines are fundamental to modern web development, separating presentation logic from application code and enabling dynamic content generation. While beneficial, their inherent ability to execute code makes them a prime target for attackers if user input is not handled with extreme care [2][3]. The vulnerability typically occurs when user-controlled data is directly concatenated into a template string or used as part of a template expression without proper sanitization, validation, or escaping [1][2][4][6].
Core Mechanics
At its heart, SSTI exploits the feature of template engines that allows them to evaluate expressions and execute code within their processing context. The vulnerability manifests when an application fails to distinguish between literal data and executable template code, particularly when this code originates from user input.
Template engines use specific syntax to denote placeholders, variables, and control structures. Common examples include double curly braces {{ ... }} (Jinja2, Twig), ${ ... } (FreeMarker, Velocity), and <%= ... %> (ERB) [2][4][6][10]. When an application incorrectly allows user-supplied input to be interpreted as part of this template syntax, an attacker can inject directives that the template engine will execute server-side.
The basic exploitation pattern involves:
1. Identifying Input Vectors: Locating any user-controllable input points within the application (e.g., URL parameters, form fields, HTTP headers, cookies) that are likely to be processed by a server-side template engine [11][5][10]. 2. Probing for Template Evaluation: Injecting basic template syntax, often simple mathematical expressions like {{77}} or ${77}, to observe if the server evaluates and renders the result (e.g., 49) instead of displaying the literal expression [2][4][5][6][10]. 3. Identifying the Template Engine: Different template engines use distinct syntaxes and have unique features. Detecting the specific engine in use is crucial for crafting targeted payloads. Error messages, successful evaluation of specific syntaxes, or the use of fingerprinting tools can aid in this identification [2][11][10]. 4. Escalating to Code Execution: Once template evaluation is confirmed, the attacker attempts to leverage the engine's capabilities to access internal objects, methods, or functions that allow arbitrary code execution or file system access [2][4][5][10].
The core of the vulnerability lies in the dynamic construction of templates from user input. A safe practice involves passing user input as data variables to a predefined template, rather than directly embedding it into the template string itself [1][2][12][13][14][10].
Notable Techniques
The exploitation of SSTI vulnerabilities is highly dependent on the specific template engine and the context in which it is used. However, several common techniques and payload patterns have emerged.
Detection Payloads
The initial step in identifying an SSTI vulnerability is to use basic template syntax that demonstrates server-side evaluation.
- Mathematical Expressions: Injecting simple arithmetic expressions is a common method. The expected result varies by engine:
{{7*7}}often yields49for Jinja2/Twig, or7777777for Jinja2 (string multiplication) [2][4][5][6][15][16][17][10].${7*7}is typically used for FreeMarker/Velocity [2][6][18][19][10].<%= 7*7 %>is characteristic of ERB (Ruby) [2][6][10].#{7*7}can be used with Thymeleaf [11][20].- Polyglot Payloads: A sequence of characters that can trigger errors or execute in multiple template engines, aiding in detection and identification. A common example is
${{<%[%'"}}%\.[11][20][7][10]. - Error Triggering: Injecting syntax that is guaranteed to cause an error (e.g.,
(1/0).zxy.zxy) can reveal the template engine through verbose error messages [11][20].
Exploitation Payloads & Techniques
Once a vulnerability is confirmed, attackers aim to leverage it for RCE or sensitive data access. The specific payloads depend heavily on the template engine and available objects/functions.
- Jinja2 (Python): This engine is widely used with Flask. Exploitation often involves navigating Python's object model.
- Accessing built-in objects like
configorrequestto retrieve sensitive information:{{ config.items() }}or{{ request }}[2][21][22][16][23]. - Using Python's object introspection (
__class__,__mro__,__subclasses__) to find powerful classes likesubprocess.Popenor_io.FileIOfor command execution or file reading:{{ ''.__class__.__mro__[1].__subclasses__()[40]('/etc/passwd').read() }}or{{ ''.__class__.__mro__[2].__subclasses__()[40]('id', shell=True, stdout=-1).communicate()[0].strip() }}[21][22][16][23][10]. - Leveraging context objects like
cycler,joiner, ornamespaceto access globals and theosmodule:{{ cycler.__init__.__globals__.os.popen('id').read() }}[2][24][25][23]. - Bypassing filters often involves using
request.args.paramorrequest.headersto pass payload parts, string concatenation (e.g.,_*2 | join), or alternative attribute access methods like|attr()` [26][27][28][16][29][23]. - Twig (PHP): Common in PHP frameworks like Symfony.
- Accessing internal Twig objects like
_selforappfor information disclosure:{{ _self.env }},{{ dump(app) }}[2][30][17]. - Executing commands via filter registration or manipulation:
{{ _self.env.registerUndefinedFilterCallback('system') }}{{ _self.env.getFilter('id') }}[2][24]. - Exploiting
evaluateorevaluate_twigfunctions with nested calls to bypass sanitization:{{ evaluate_twig("system('id')") }}[31][32][17]. - Sandbox bypasses often involve exploiting weak regex in sanitization functions like
cleanDangerousTwig[30][31]. - FreeMarker (Java): Used in Java applications.
- Using the
Executeutility class for command execution:<#assign ex="freemarker.template.utility.Execute"?new()>${ ex("id")}[2][33][34][18][35][36][19]. - Leveraging reflection or object wrappers to bypass restrictions:
#(classloader=article.class.protectionDomain.classLoader)# #(owc=classloader.loadClass("freemarker.template.ObjectWrapper"))# #(dwf=owc.getField("DEFAULT_WRAPPER").get(null))# #(ec=classloader.loadClass("freemarker.template.utility.Execute")) ${dwf.newInstance(ec,null)("id")}[33][36][19]. - The
?lower_abcor?upper_abcbuilt-ins can be used to encode characters and bypass blacklists [36]. - ERB (Ruby): Default in Ruby on Rails.
- Direct command execution using
system,exec, or backticks:<%= system('id') %>or<%=whoami%>[2][37][38][39][15][40]. - File operations like
File.openare often blocked by safe level settings but can sometimes be exploited [37][39][40]. - Introspection of
selforsessionobjects to discover application internals [37]. - Text Template Files (.NET):
TextTransform.exe,TextTransformCore.exe,t4.exe, andMSBuild.execan process.ttfiles containing C# or VB code. TextTransform.exeandTextTransformCore.execan execute C# or VB code within.tttemplates [41].t4.exe(fromdotnet-t4package) can also process.ttfiles [41].MSBuild.execan be leveraged by manipulating.csprojfiles to include malicious.ttfiles, triggering template processing during the build [41].- Jelly (ServiceNow): A template language used in ServiceNow that can be vulnerable to SSTI. Payloads often involve injecting
tags to execute code or disclose data [42][43].
Detection & Prevention
Effective detection and prevention of SSTI vulnerabilities require a multi-layered approach focusing on secure coding practices and vigilant monitoring.
Detection
- Input Fuzzing: Use automated scanners or manual techniques to fuzz input fields with common template syntax (e.g.,
{{...}},${...},<%=...%>,${{<%[%'"}}%\.) and analyze responses for template evaluation, errors, or unexpected behavior [11][5][7][17][10]. - Error Message Analysis: Pay close attention to verbose error messages that might reveal the template engine or application structure [2][11][10].
- Behavioral Analysis: Monitor for unusual process creations (e.g.,
TextTransform.exespawning unexpected children) or increased file I/O, especially around directories likeC:\Users\when MSBuild is involved [41].\AppData\Local\Temp - Log Analysis: Correlate process creation telemetry with suspicious child processes and monitor for outbound communication attempts from templating utilities [41].
- Version Checks: Ensure template engines and related frameworks are updated to patched versions to mitigate known vulnerabilities [44][45][34].
Prevention
- Avoid User Input in Templates: The most critical principle is to never concatenate or directly embed user-controlled input into template strings. Instead, pass user input as data variables into predefined, static templates [1][2][6][12][13][14][9][10].
- Sanitize and Validate Input: Strictly validate and sanitize all user input before it is used, even if it's intended to be treated as data. This includes escaping special characters that could be misinterpreted by the template engine [1][4][6][12][7][14].
- Use Template Engine Sandboxing: If user-supplied templates are unavoidable (e.g., for highly configurable features), leverage the sandboxing capabilities of the template engine. Configure it to restrict access to dangerous built-in functions, classes, and methods [44][2][46][4][12][47][9][10].
- Disable Dangerous Features: Turn off or limit advanced template engine features that could lead to code execution or sensitive data exposure.
- Use Secure Coding Patterns: Prefer functions like
render_template()in Flask overrender_template_string()when dealing with dynamic content, ensuring input is passed as context variables [12][14][10]. - Maintain Dependencies: Keep template engines and their surrounding frameworks updated to the latest secure versions [44][45][48].
- Principle of Least Privilege: Ensure the application runs with minimal necessary privileges. This limits the impact if an SSTI vulnerability is exploited [49].
- Input Validation and Whitelisting: Implement strict validation, including URL whitelisting and rejecting private IP ranges, especially if input is used in contexts that might fetch external resources [6].
- Web Application Firewalls (WAFs): Deploy WAFs with up-to-date rulesets that can detect common SSTI patterns. However, WAFs should be considered a defense-in-depth measure, not a sole solution, as they can be bypassed [6].
- Static Analysis (SAST): Integrate SAST tools into CI/CD pipelines to flag insecure template rendering practices and dangerous function calls before code reaches production [13][50].
Tooling
Several tools exist to aid in the detection and exploitation of SSTI vulnerabilities.
- Tplmap: An older but comprehensive tool written in Python 2.7 that supports numerous template engines and offers sandbox escape techniques. It can automate detection, identification, and exploitation, including OS command execution and file system access [2][11][51][52].
- SSTImap: A modern Python 3 alternative to Tplmap, offering an interactive interface and enhanced features for detection and exploitation [2][11][14][52].
- Hackmanit/TInjA: An SSTI and Cross-Site Scripting (CSTI) scanner utilizing novel polyglots for detection [11][20][52].
- Nuclei: A popular template-based vulnerability scanner that can be configured with custom templates to detect SSTI vulnerabilities in various applications [42][43].
- Burp Suite Extensions: Various Burp Suite extensions and plugins can assist in fuzzing and identifying template engines [2][53][16][17].
Recent Developments
The landscape of SSTI vulnerabilities continues to evolve, with new techniques and targets emerging regularly.
- Supply Chain Attacks:
.ttfiles used withTextTransform.exe,TextTransformCore.exe,t4.exe, andMSBuild.exehave been identified as potential vectors for supply chain compromises, allowing code execution at build time or within CI/CD pipelines [41]. - Complex Sandbox Bypasses: Attackers are continually developing more sophisticated methods to bypass sandbox restrictions in template engines like Twig, Jinja2, and FreeMarker, often by chaining together multiple built-in functions or exploiting obscure language features [2][33][29][10].
- Targeting Specific Frameworks/Applications: Numerous CVEs highlight SSTI vulnerabilities in popular frameworks and applications, including Grav CMS [30][46][31], Flask/Jinja2 [21][54][22][12][13][16][23], Thymeleaf [44][48][55][18], Spring Boot [56][55], Apache Camel [57], OpenMetadata [58], Tandoor Recipes [49][59], and ServiceNow [42][60][43].
- AST Injection: In JavaScript environments, particularly with engines like Handlebars and Pug, Abstract Syntax Tree (AST) injection combined with prototype pollution can lead to RCE [61].
- Method Confusion in Go: Server-side template injection in Go applications, specifically within the
html/templateandtext/templatepackages, can lead to file reads and RCE through method abuse [62][63][64].
Where to Go Deeper
For practitioners seeking to deepen their understanding of SSTI, the following resources offer valuable insights and practical guidance:
- PortSwigger Web Security Academy: Offers comprehensive articles, labs, and learning modules on SSTI, covering detection, exploitation, and prevention across various template engines [9][65].
- HackTricks: A vast repository of security knowledge, including detailed sections on SSTI, engine-specific payloads, and bypass techniques [1][66][23][16].
- PayloadsAllTheThings: A GitHub repository that serves as a comprehensive cheat sheet for various vulnerabilities, including extensive lists of SSTI payloads for numerous template engines and languages [11][38][67][20][16][19][52].
- OWASP Testing Guide: Provides standard methodologies for testing web applications, including specific guidance on identifying and exploiting SSTI vulnerabilities [17].
- Blog Posts and Writeups: Numerous security blogs and researchers regularly publish detailed analyses of specific SSTI vulnerabilities, providing real-world examples and advanced exploitation techniques. Sites like Medium, Intigriti, Synack, and individual researcher blogs are excellent sources [44][2][30][4][21][33][37][54][22][68][69][70][26][27][71][12][13][72][48][50][61][73][7][15][74][75][34][55][18][76][62][63][64][8][42][60][43][25][59][49][53][28][77][58][78][57][35][36][29][40].
- Exploit Databases and Metasploit Modules: Platforms like Exploit-DB and the Metasploit Framework often contain publicly available exploits and modules for known SSTI vulnerabilities, offering practical examples [79][80][42].
- CTF Challenges and Labs: Participating in Capture The Flag (CTF) competitions and practicing in dedicated SSTI labs (e.g., from PortSwigger, Inj3ctlab) provides hands-on experience in identifying and exploiting these vulnerabilities [4][81][82][83][53][65].