TASK-014: Add log path validation to prevent arbitrary file access
Restrict monitored log paths to a configurable allowlist of safe directories to prevent authenticated users from instructing fail2ban to monitor arbitrary files on the system, which could leak contents via fail2ban logging. Changes: - Add 'allowed_log_dirs' setting to Settings (defaults to /var/log, /config/log) - Add @field_validator to AddLogPathRequest to validate log paths at request time - Validator resolves paths to canonical form and checks against allowed prefixes - Use Path.is_relative_to() to prevent prefix bypass attacks like /var/log_evil - Add comprehensive tests for valid/invalid paths and symlink handling - Update Features.md and Backend-Development.md with security documentation Security improvements: - Blocks access to sensitive files (/etc/shadow, /etc/passwd, etc.) - Resolves symlinks before validation to prevent escape routes - Uses proper path comparison instead of string prefix matching - Configurable via BANGUI_ALLOWED_LOG_DIRS environment variable Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -553,6 +553,35 @@ BANGUI_FAIL2BAN_START_COMMAND='"/opt/my tools/fail2ban" start' # Quoted path
|
||||
**Common Pitfall:**
|
||||
Using `.split()` instead of `shlex.split()` would break commands with spaces in paths. Always use quoted strings for paths that contain whitespace.
|
||||
|
||||
### Log Path Validation & Allowlisting
|
||||
|
||||
Authenticated users can instruct fail2ban to monitor additional log files through the API endpoint `POST /api/config/jails/{name}/logpath`. To prevent path-traversal attacks and unauthorized reads of sensitive system files, all requested log paths must resolve to locations within a configurable allowlist of safe directories.
|
||||
|
||||
**Allowed Directories:**
|
||||
- Configured via the `BANGUI_ALLOWED_LOG_DIRS` environment variable (comma-separated list).
|
||||
- Defaults to: `["/var/log", "/config/log"]`.
|
||||
|
||||
**Path Validation Rules:**
|
||||
1. The requested path is resolved to its canonical form using `Path(log_path).resolve()`, which:
|
||||
- Expands relative paths to absolute paths.
|
||||
- Resolves symbolic links to their real targets.
|
||||
- Normalizes `.` and `..` components.
|
||||
2. The resolved path is checked using `Path.is_relative_to()` against each allowed directory prefix.
|
||||
3. If the resolved path is not relative to any allowed directory, a `ValueError` is raised with a descriptive error message.
|
||||
|
||||
**Implementation:**
|
||||
- Validation occurs in the Pydantic model `AddLogPathRequest` using a `@field_validator`.
|
||||
- The validator runs at request time, before the service layer is invoked.
|
||||
- Symlinks that escape allowed directories are rejected (see [symlink bypass tests](../../backend/tests/test_models.py)).
|
||||
|
||||
**Important:** Use `is_relative_to()`, not `startswith()` or string prefix matching. The latter is bypassable with paths like `/var/log_evil/file.log`.
|
||||
|
||||
**Environment Variables:**
|
||||
```bash
|
||||
BANGUI_ALLOWED_LOG_DIRS="/var/log,/config/log" # Default
|
||||
BANGUI_ALLOWED_LOG_DIRS="/var/log,/config/log,/home/app/logs" # Custom directory
|
||||
```
|
||||
|
||||
### Login Rate Limiting
|
||||
|
||||
The login endpoint (`POST /api/auth/login`) is protected against brute-force attacks using an in-memory rate limiter.
|
||||
|
||||
Reference in New Issue
Block a user