← Back to Writeups
PORTSWIGGERN/ASSTI

Server-side template injection using documentation

XESXOR9/2/20262 min read
#ssti#portswigger#web-security-academy

Server-side template injection using documentation

Platform: PortSwigger | Category: SSTI | Type: Lab | Difficulty: N/A | OS: N/A | Author: XESXOR | Date: 2026-08-24 | Status: Solved Techniques: Web Security Academy, SSTI

Summary

Walkthrough of the PortSwigger Web Security Academy lab Server-side template injection using documentation (SSTI). This lab demonstrates a ssti vulnerability and its exploitation to achieve the lab objectives.

Lab Overview

PortSwigger Web Security Academy — SSTI

This writeup is part of the XESXOR PortSwigger collection. The original lab description and solution have been preserved and reformatted for clarity.

Lab Description :

image

Overview :

In addition to providing the fundamentals of how to create and use templates, the documentation may also provide some sort of "Security" section.

This can be an invaluable resource, even acting as a kind of cheat sheet for which behaviors you should look for during auditing, as well as how to exploit them.

For example, in ERB, the documentation reveals that you can list all directories and then read arbitrary files as follows:

bash
<%= Dir.entries('/') %>
<%= File.open('/example/arbitrary-file').read %>

Solution :

Login to the website using the credentials - content-manager:C0nt3ntM4n4g3r.

image

image

So here we have an option to edit out template. When we enter ${{<%[%'"}}%\ & save the template , it doesn't return anything which means it caused an error at the backend. This confirms the SSTI vulnerability.

Identifying the template engine -

When we enter ${9/0} (divide by zero expression), we get an error in the response indicating that the template engine used is Freemarker.

image

Executing arbitrary code -

We can run code on Freemarker using this -

java
${"freemarker.template.utility.Execute"?new()("id")}

Reference

On previewing the template after entering the following payload gives us the id as carlos.

image

To delete this just replace the id command to rm /home/carlos/morale.txt

java
${"freemarker.template.utility.Execute"?new()("rm /home/carlos/morale.txt")}

And we have successfully solved the lab.

image

Key Takeaways / Lessons

  • Understanding SSTI detection and exploitation is crucial for web security.
  • Always validate and sanitize user input; implement proper access controls.
  • This lab is part of the PortSwigger Web Security Academy — practice in a safe, legal environment.

Crafted by XESXOR Research • 2026-08-24 • PortSwigger Web Security Academy • Lab: Server-side template injection using documentation