- Challenge Statement :- I made a cool website where you can announce whatever you want! Try it out. Additional details will be available after launching your challenge instance .
- Now here in this website we have to make the announcements and then observe the response . So from the challenge we have known that here we have to implement the Server Side Template Injection .
Press enter or click to view image in full size
- Templates :- This are the files that enables the the developers to generate the dynamic web pages by placing the placeholders for the variables. Because other wise this would become a manual tedious job for them to update the variable for each user. This is done automatically by the template engine .
- Server Side Template Injection :- This is the type of injection that occurs in the templates when it does not properly validate the user input and sometimes also executes the user instructions in some of the cases . For example in the image below .
Press enter or click to view image in full size
- Now what happens is that it becomes dangerous because it allows for the remote code execution, access to the configurations objects, secret keys and system internals and etc .
- So first in the challenge we will start by checking that which of the template is being used in this challenge and then we will construct our payload . So we will give the inputs like {{ 8*8 }}, ${ 8*8 } and then notice where does it gives the answer .
- Checking for {{ 8*8 }}
Press enter or click to view image in full size
- So in this we got the output . Let’s Try Others As Well .
Press enter or click to view image in full size
- So we saw that in other cases we did not get the result it just produced the as it is input. So know we have known that this template executes the instructions inside the {{variable }} .
- So below in the image i have attached the some of the types of templates with their supported formats and the languages.
- So from this we can get the idea that the template in our webpage can be the Jinja2, Handlebar, Twig. So first we test for the Jinja2 by inserting the {{ config }}, {{ self }} etc .
Press enter or click to view image in full size
- And yes we got he valid output for the {{ self }} and {{ config }} and this confirms the Jinja2 template so now before seeing to the final payload we must first understand some of the import functions, dictionaries, objects, commands to fully understand the final payloads .
- {{ config }} :- This is flask configuration object which contains the configuration files information, secret keys, database urls, settings, session configurations. Below we have tried for the {{ config }}, {{ config.items }}, {{ config.__class__.__init__.__globals__ }} .
- {{ request }} :- It is the flask request object which represents the current HTTP request . Here we have checked for the {{ request.application }}, {{ request.method }}, {{ request.url }}, {{ request.headers }} .
- {{ self }} :- This is the template reference object which sometimes information about the system internals. Generally we test for the {{ self }}, {{ self.__init__.__globals__ }} .
- {{__init__}} :- This is the constructor method object .
- {{__globals__}} :- This is the dictionary of the every object which contains all the global variables, built in preferences, tools, libraries, functions .
- {{__import__(’os’) }} :- This function is executed when we write the import os in the code .
- popen(’ls’).read() :- This is used for the execution of the command on the system and read() is used for the human readable text produced otherwise we will get the object reference output .
- {{__builtins__}} :- This contains the various libraries and functions like import, open, exec, eval and etc .
- So we have understood the all the necessary concepts now we have used the 4 types of payload that would give us the flag. The above explanation will help to connect each every component of payload that why we wrote this object, library in this. So here are they :-
{{ self.__init__.__globals__.__builtins__.__import__(’os’).popen(’ls’).read() }}
Get Devansh Patel’s stories in your inbox
Join Medium for free to get updates from this writer.
{{ self.__init__.__globals__.__builtins__.open(’flag’) }}
{{ request.application.__globals__.__builtins__.__import__(’os’).popen(’ls’).read() }}
{{ config.__class__.__init__.__globals__[’os’].popen(’cat flag’).read() }}
Press enter or click to view image in full size
- Learning of the concepts of from this writeup :-
- Template and Template Meaning .
- Server Side Template Injection Meaning .
- Jinja2, Handlebar, Freemaker, Twig, Smarty, ERB Templates and Their Formats .
- {{ config }}, {{ request }}, {{ self }}.
- popen, read, init, globals, import functions and dictionaries .
Final Takeway
Easy challenges are not about “easy flags”. They are about building the foundation for harder ones .
This SSTI challenge was not just about typing {{ 8*8 }} and seeing 64.
It was about training your brain to:
a. Identify template engines instead of guessing blindly.
b. Test payload patterns methodically.
c. Understand why {{ }} works but ${ } doesn’t.
d. Explore objects like config, request, and self with intent.
e. Trace how __init__, __globals__, and __builtins__ connect internally.
Most people stop when they get code execution. But the real learning starts when you ask:
Why did this payload work?
How did it reach the os module?
What object chain allowed access to system commands?
How does Jinja2 expose Python internals?
It is about understanding how templating engines process input. It is about understanding how templating engines process input. How objects are structured in memory. How Python exposes global namespaces. How unsafe rendering turns logic into execution.
If you only copy-paste payloads, you will solve easy challenges. If you understand the object traversal path, you will solve the hard ones. CTFs are not about the flag. They are about learning how applications actually break.
Go deeper than the payload. Go deeper than the writeup. Go deeper than the solution.
More templates. More internals. More real exploitation.