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.
|
||||
|
||||
@@ -212,11 +212,12 @@ A page to inspect and modify the fail2ban configuration without leaving the web
|
||||
|
||||
- Option to register additional log files that fail2ban should monitor.
|
||||
- For each new log, specify:
|
||||
- The path to the log file.
|
||||
- The path to the log file (must be within allowed directories to prevent unauthorized access to sensitive files).
|
||||
- One or more regex patterns that define what constitutes a failure.
|
||||
- The jail name and basic jail settings (ban time, retries, etc.).
|
||||
- Choose whether the file should be read from the beginning or only new lines (head vs. tail).
|
||||
- Preview matching lines from the log against the provided regex before saving, so the user can verify the pattern works.
|
||||
- **Log Path Security:** Added log paths must resolve to locations within a configured allowlist of safe directories (default: `/var/log` and `/config/log`). This prevents authenticated users from instructing fail2ban to monitor sensitive system files. Paths containing symlinks are resolved to their canonical targets before validation.
|
||||
|
||||
### Regex Tester
|
||||
|
||||
@@ -264,7 +265,7 @@ A page to inspect and modify the fail2ban configuration without leaving the web
|
||||
- Truncation notice when the total log file line count exceeds the requested tail limit.
|
||||
- Container automatically scrolls to the bottom after each data update.
|
||||
- When fail2ban is configured to log to a non-file target (STDOUT, STDERR, SYSLOG, SYSTEMD-JOURNAL), an informational banner explains that file-based log viewing is unavailable.
|
||||
- The log file path is validated against a safe prefix allowlist on the backend to prevent path-traversal reads.
|
||||
- Log file paths are validated against a configurable allowlist of safe directories on the backend to prevent unauthorized reads of sensitive system files.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user