fix(scanner): avoid SVG/XML false positives; add allowlist and .gitignore
Relax payload scanner for XML/SVG by passing content-type into checks Skip JS-style eval() detection when content-type is XML/SVG Pass request Content-Type through sniff_file_for_php_payload() and raw-body checks Add common XML/SVG content-types to allowlist.json Add repository .gitignore (ignore logs, quarantine/, state/, env, vendor, IDE files)
This commit is contained in:
58
README.md
Normal file
58
README.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Upload Logger (Hardened v3)
|
||||
|
||||
This repository contains the v3 upload-logging helper: a hardened single-file monitor that logs uploads, detects common evasion techniques, and optionally blocks suspicious uploads.
|
||||
|
||||
Primary file: [upload-logger.php](upload-logger.php)
|
||||
|
||||
Summary
|
||||
- Purpose: Log normal uploads and raw-body uploads, detect double-extension tricks, fake images, PHP payloads embedded in files, and provide flood detection.
|
||||
- Runs only for HTTP requests; recommended to enable via `auto_prepend_file` in a per-site PHP-FPM pool for broad coverage.
|
||||
|
||||
Key configuration (top of `upload-logger.php`)
|
||||
- `$logFile` — path to the log file (default: `__DIR__ . '/logs/uploads.log'`).
|
||||
- `$BLOCK_SUSPICIOUS` — if `true` the script returns `403` and exits when suspicious uploads are detected.
|
||||
- `$MAX_SIZE` — threshold for `WARN big_upload` (default 50 MB).
|
||||
- `$RAW_BODY_MIN` — minimum raw request body size considered suspicious when `$_FILES` is empty (default 500 KB).
|
||||
- `$FLOOD_WINDOW_SEC`, `$FLOOD_MAX_UPLOADS` — lightweight per-IP flood detection window and max uploads before alerting.
|
||||
- `$SNIFF_MAX_BYTES`, `$SNIFF_MAX_FILESIZE` — parameters controlling fast content sniffing for PHP/webshell markers.
|
||||
- `$LOG_USER_AGENT` — include `User-Agent` in logs when true.
|
||||
|
||||
What it detects
|
||||
- Dangerous filenames (path-traversal, double extensions, hidden php-like dotfiles).
|
||||
- Fake images: file extension indicates an image but `finfo` returns a non-image MIME.
|
||||
- PHP/webshell markers inside file content (fast head-scan up to configured limits).
|
||||
- Archive uploads (`.zip`, `.tar`, etc.) flagged for attention.
|
||||
- Raw request bodies (e.g., `application/octet-stream` or streamed uploads) when `$_FILES` is empty and body size exceeds `$RAW_BODY_MIN`.
|
||||
- Flooding by counting uploads per-IP in a rolling window.
|
||||
|
||||
Logging and alerts
|
||||
- Each accepted upload generates an `UPLOAD` line with fields: `ip`, `user`, `name`, `size`, `type`, `real` (detected MIME), `tmp`, `uri`, and optional `ua`.
|
||||
- Suspicious uploads generate `ALERT suspicious` entries with `reasons=` listing detected flags (e.g., `bad_name,fake_image,php_payload`).
|
||||
- Other notes: `WARN big_upload`, `NOTE archive_upload`, `MULTIPART_NO_FILES`, and `RAW_BODY` are emitted when appropriate.
|
||||
|
||||
Integration notes
|
||||
- Preferred deployment: set `php_admin_value[auto_prepend_file]` in the site-specific PHP-FPM pool to the absolute path of `upload-logger.php` so it runs before application code.
|
||||
- If using sessions for user identification, the script safely reads `$_SESSION['user_id']` only when a session is active; do not rely on it being present unless your app starts sessions earlier.
|
||||
- The script uses `is_uploaded_file()`/`finfo` where available; ensure the PHP `fileinfo` extension is enabled for best MIME detection.
|
||||
|
||||
Operational recommendations
|
||||
- Place the `logs/` directory outside the webroot or deny web access to it.
|
||||
- Ensure correct owner/group and permissions (e.g., owner `root`, group `www-data`, `chmod 750` on `.security` and `chmod 640` for logs) and confirm PHP-FPM's user/group membership.
|
||||
- Rotate logs with `logrotate` (see `INTEGRATION.md` for an example snippet).
|
||||
- If your host uses SELinux/AppArmor, set correct contexts or adjust profiles so PHP-FPM can read the script and write logs.
|
||||
|
||||
Limitations & safety
|
||||
- This script improves visibility and blocks common upload tricks but cannot guarantee interception of every file-write vector (e.g., direct application writes, ZipArchive extraction, custom file APIs). Use it as part of a layered defense.
|
||||
- Content sniffing is limited to a head-scan to reduce CPU and false positives; tune `$SNIFF_MAX_BYTES` and `$SNIFF_MAX_FILESIZE` to balance coverage and performance.
|
||||
|
||||
Quick start
|
||||
1. Place `upload-logger.php` in a per-site secure folder (see `INTEGRATION.md`).
|
||||
2. Ensure the `logs/` directory exists and is writable by PHP-FPM.
|
||||
3. Enable as an `auto_prepend_file` in the site pool and reload PHP-FPM.
|
||||
4. Monitor `logs/uploads.log` and adjust configuration options at the top of the script.
|
||||
|
||||
Support & changes
|
||||
- For changes, edit configuration variables at the top of `upload-logger.php` or adapt detection helpers as needed.
|
||||
|
||||
---
|
||||
Generated for upload-logger.php (v3).
|
||||
Reference in New Issue
Block a user