SSTI Code Review Lab 2

Table of contents

Lab Setup
Create a folder for the challenge.
mkdir ssti_ctf2_challenge cd ssti_ctf2_challenge
Set up the environment
python3 -m venv venv source venv/bin/activate pip install Flask
Create
app.py
from flask import Flask, request, render_template_string app = Flask(__name__) @app.route('/') def index(): return ''' <h1>Welcome to the SSTI Code Review Lab 2!</h1> <form method="POST" action="/submit"> <table> <tr> <td><label for="name">Name:</label></td> <td><input type="text" id="name" name="name" placeholder="Enter your name" required /></td> </tr> <tr> <td><label for="feedback">Feedback:</label></td> <td><input type="text" id="feedback" name="feedback" placeholder="Enter your feedback" required /></td> </tr> <tr> <td colspan="2" style="text-align: center;"> <input type="submit" value="Submit" /> </td> </tr> </table> </form> ''' @app.route('/submit', methods=['POST']) def submit(): name = request.form['name'] feedback = request.form['feedback'] # Vulnerable to SSTI: directly rendering user input without sanitization template = f''' <h1>Hello, {name}!</h1> <p>Your feedback: {feedback}</p> <p>Try injecting a template expression!</p> ''' return render_template_string(template) if __name__ == '__main__': app.run(debug=True)
Run the Application
python app.py
We now have our web app ready.
Try the
SSTI payload now
and submit:-
{{ 7*7 }}
- {{config}}
- I am using
{{ 7*7 }}
for Name and{{5*5}}
for Feedback
- I am using
Now, we can see our
SSTI payload
is working correctly.Let me try this payload
{{config}}
in the feedback now.Causes of this vulnerability
F-String Usage: Directly using f-strings to interpolate user input into the template, allowing code execution.
No Input Validation: User input is not validated or sanitized before rendering.
Raw Template Rendering: Using
render_template_string
with unescaped user input.Lack of Escaping Mechanisms: Failing to utilize escaping functions to prevent injection attacks.
Assuming User Input is Safe: Trusting user input without proper checks leads to vulnerabilities.
Code Review
Vulnerable code snippet
template = f''' <h1>Hello, {name}!</h1> <p>Your feedback: {feedback}</p> <p>Try injecting a template expression!</p> ''' return render_template_string(template)
Prevention Code
Use
render_template
instead ofrender_template_string
to automatically escape user input.from flask import render_template @app.route('/submit', methods=['POST']) def submit(): name = request.form['name'] feedback = request.form['feedback'] return render_template('response.html', name=name, feedback=feedback)
Use html page instead of fstring. Do not use f-strings or similar methods for rendering user input directly.
# Avoid this: template = f''' <h1>Hello, {name}!</h1> '''
We can also use the built-in
escape
function to clean user input before rendering. If the above prevention method is not followed.from flask import escape @app.route('/submit', methods=['POST']) def submit(): name = escape(request.form['name']) feedback = escape(request.form['feedback']) template = f''' <h1>Hello, {name}!</h1> <p>Your feedback: {feedback}</p> ''' return render_template_string(template)
Subscribe to my newsletter
Read articles from Abishek Kafle directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Abishek Kafle
Abishek Kafle
Infosec Poet and CAP-certified DevOps/SecOps Engineer, passionate about security, creativity, and continuous learning.