T05 · Unauthorized Access and Privilege Escalation
- Location
server.py:758- Finding
Arbitrary Local File Disclosure Through Unrestricted Catch-All Route
- Content
View full analysis
') def serve_file(filepath): if '..' in filepath or filepath.startswith('/'): return "Invalid path", 403 full_path = os.path.join('/', filepath) if os.path.exists(full_path) and os.path.isfile(full_path): return send_from_directory(os.path.dirname(full_path), os.path.basename(full_path)) return "File not found", 404 ``` ### Technical Analysis The catch-all route treats the URL path as a filesystem path rooted at `/`. The check for `..` does not provide confinement because an attacker does not need directory traversal sequences. For example, the URL path `etc/passwd` is converted into `/etc/passwd`. The route then returns any file for which the Flask process has read permission. It is not restricted to the configured image output directory, project directory, or records associated with a valid work item. On Windows, behavior differs according to drive and path handling, but known paths on the current drive may still be exposed. The application must not rely on the operating system to prevent disclosure. ### Attack Path 1. An attacker connects to the service on port 697. 2. The attacker requests a known local path without a leading slash in the route parameter, such as `/etc/passwd`. 3. The handler constructs `/etc/passwd`. 4. If the service account can read the file, Flask sends it to the attacker. 5. The attacker repeats the process for application files, database files, configuration, credentials, or user documents. ### Impact Assessment A remote, unauthenticated attacker may read any file available to the server account. Potential targets include: - The `.env` file containing `API_KEY` and `PLATFORM_TOKEN` - `data/works.db`, including prompts, task IDs, output paths, and API responses - Source code and config ...[truncated 281 chars]- Remediation
View remediation
