T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- server.py:758
- Finding
- Arbitrary Local File Disclosure Through Unrestricted Catch-All Route<![CDATA[ ## Vulnerability Details **File Location**: `server.py:758-764` **Vulnerability Type**: Arbitrary local file read **Risk Level**: Critical ### Complete Code Snippet ```python @app.route('/<path:filepath>') 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
- <![CDATA[ ## Remediation Suggestions 1. Remove the catch-all filesystem-serving route. 2. Serve generated images only through a dedicated route that accepts an opaque work ID and validates the corresponding database record. 3. Restrict all served files to `SAVE_BASE_PATH` or another dedicated content directory. 4. Resolve and canonicalize the requested path, then verify it remains inside the approved directory. 5. Use Flask/Werkzeug safe-path facilities such as `safe_join` and reject absolute paths. 6. Require authentication and authorization before returning private generated content. 7. Run the process under a dedicated account with minimal filesystem permissions. 8. Rotate API credentials if the vulnerable service has been exposed to untrusted networks. ]]>
