portswigger-all-labs

Complete PortSwigger Web Security Academy Lab Writeups Detailed, categorized solutions for every lab — from APPRENTICE to EXPERT — covering all 30 vulnerability types.

View on GitHub

Server-Side Template Injection (SSTI) Guide


Overview

Server-Side Template Injection (SSTI) occurs when user-controlled input is embedded directly into a server-side template and evaluated as code. This vulnerability can lead to information disclosure, arbitrary file access, or even remote code execution (RCE).

Template engines are designed to render dynamic content by combining templates with data. However, when untrusted input is injected into templates without proper sanitization, attackers can manipulate the rendering logic and execute arbitrary code on the server.


Constructing an SSTI Attack

SSTI Concept

1. Detection Phase

A. Identify User Input Reflection

Locate areas where user input is reflected in the server response. These can often be discovered via manual inspection or interception proxies such as Burp Suite.

B. Fuzz with Polyglot Payloads

Use polyglot payloads containing syntax elements from multiple template engines to detect potential SSTI:

POST /endpoint HTTP/1.1
Host: vulnerable-site.com
parameter=$%\.

If the server’s response changes, produces an error, or displays evaluated expressions, SSTI may be present.

C. Observe Server Responses

Indicators of SSTI include:


2. Syntax Testing: Determine Template Context

A. Plaintext Context

Test with simple arithmetic expressions:

${7*7}

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

If the output returns 49, your payload was evaluated — confirming SSTI.

B. Expression Context

When user input is directly inserted into an active expression, attempt to break the syntax:

engine.render("Hello +greeting+", data)

Then test with:

/greeting=data.username
/greeting=data.username}}hello

If closing the expression (}}) affects rendering or triggers an error, SSTI is likely.


Identification Phase: Determine the Template Engine

Once SSTI is verified, identifying the specific template engine is crucial for crafting engine-specific payloads.

A. Trigger and Analyze Errors

Inject malformed expressions:

${}

<%= %>
${foobar}

<%= foobar %>
${7/0}

<%= 7/0 %>

Error messages or stack traces may reveal the engine name (e.g., Jinja2, Twig, Freemarker, etc.).

Error Output


B. Test Engine-Specific Syntax

If no explicit error message appears, test common syntaxes for popular engines:

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

If a specific syntax evaluates correctly (21), it identifies the underlying template engine.

Syntax Detection


Exploitation Phase

Step 1: Review Documentation

Study engine-specific documentation or resources like HackTricks to identify:


Step 2: Enumerate Accessible Objects

Attempt to access key objects:






If unavailable, perform brute-force enumeration using SecLists or Burp Intruder wordlists of potential variables and object attributes such as:

__class__, __mro__, __subclasses__

Step 3: Execute Payloads

Once internal objects are accessible, escalate to RCE or file access.

Example (Jinja2):



Tools

Tplmap

Tplmap automates the detection and exploitation of SSTI vulnerabilities.

Usage Examples:

python2.7 tplmap.py -u 'http://target.com/page?name=John*' --os-shell
python2.7 tplmap.py -u "http://target.com/page?user=*&comment=hello"
python2.7 tplmap.py -u "http://target.com/ti?user=InjectHere*&comment=A" --level 5 -e jade

Summary: SSTI Exploitation Workflow

1. Identify user input reflection
2. Inject polyglot payload: $%\.
3. Test for evaluation (, ${7*7}, <%= 7*7 %>)
4. Observe output or error to confirm SSTI
5. Determine the template engine by syntax or stack trace
6. Enumerate internal objects
7. Exploit: Execute commands, read files, escalate privileges

Summary Notes: “Template Engines Injection 101” by 0xAwali

Source: Template Engines Injection 101 – @0xAwali


🔍 Overview

The post explores how Server-Side Template Injection (SSTI) vulnerabilities arise, how to detect them, and how different engines behave under injection. It also provides payloads and error-based fingerprinting methods for accurate engine identification.


⚙️ Covered Template Engines

Language Template Engines
JavaScript EJS, Handlebars, Vue, Pug
Python Jinja2, Tornado, Django, Mako
Ruby ERB, Slim, HAML
PHP Twig, Smarty, Blade
Java Velocity, Freemarker, Thymeleaf
Go text/template, html/template

📊 Language Summaries

JavaScript Summary:

JavaScript Summary

Python Summary:

Python Summary

Ruby Summary:

Ruby Summary

PHP Summary:

PHP Summary

Java Summary:

Java Summary

Go Summary:

Go Summary


🧩 Universal Payloads

After analysis, it was observed that 15 universal payloads could detect or exploit most template engines:

All Template Payloads


🧠 Key Concepts

  1. SSTI Definition: Untrusted input executed in the server’s template engine.
  2. Goal: Achieve arbitrary code execution or sensitive data access.
  3. Risk: Leads to RCE, file disclosure, and system compromise.

🧰 Practice Resources

Ideal for CTF participants, bug bounty hunters, and security professionals.


⚠️ Ethical Use

Always test SSTI only in authorized environments such as CTFs, labs, or your own applications. Never use these payloads against live systems without explicit permission.


📚 Takeaway

This article by @0xAwali provides one of the most comprehensive overviews of SSTI, covering detection, identification, and exploitation across multiple programming languages.


References