# πŸ” Per-Site PHP Upload Guard Integration Guide This guide explains how to integrate a global PHP upload monitoring script using `auto_prepend_file`, on a **per-site basis**, with isolated security folders. --- ## πŸ“ 1. Recommended Folder Structure Each website should contain its own hidden security directory: ``` /var/www/sites/example-site/ β”œβ”€β”€ public/ β”œβ”€β”€ app/ β”œβ”€β”€ uploads/ β”œβ”€β”€ .security/ β”‚ β”œβ”€β”€ upload_guard.php β”‚ └── logs/ β”‚ └── uploads.log ```` Benefits: - Per-site isolation - Easier debugging - Independent log files - Reduced attack surface --- ## πŸ”§ 2. Create the Security Directory From the site root: ```bash cd /var/www/sites/example-site mkdir .security mkdir .security/logs ```` Set secure permissions: ```bash chown -R root:www-data .security chmod 750 .security chmod 750 .security/logs ``` --- ## πŸ“„ 3. Install the Upload Guard Script Create the script file: ```bash nano .security/upload_guard.php ``` Paste your hardened upload monitoring script. Inside the script, configure logging: ```php $logFile = __DIR__ . '/logs/uploads.log'; ``` Lock the script: ```bash chown root:root .security/upload_guard.php chmod 644 .security/upload_guard.php ``` --- ## βš™οΈ 4. Enable auto_prepend_file (Per Site) ### Option A β€” PHP-FPM Pool (Recommended) Edit the site’s PHP-FPM pool configuration: ```bash nano /etc/php/8.x/fpm/pool.d/example-site.conf ``` Add: ```ini php_admin_value[auto_prepend_file] = /var/www/sites/example-site/.security/upload_guard.php ``` Reload PHP-FPM: ```bash systemctl reload php8.x-fpm ``` # πŸ” Per-Site PHP Upload Guard Integration Guide This guide explains how to integrate a global PHP upload monitoring script using `auto_prepend_file`, on a **per-site basis**, with isolated security folders. --- ## πŸ“ 1. Recommended Folder Structure Each website should contain its own hidden security directory: ```text /var/www/sites/example-site/ β”œβ”€β”€ public/ β”œβ”€β”€ app/ β”œβ”€β”€ uploads/ β”œβ”€β”€ .security/ β”‚ β”œβ”€β”€ upload-logger.php β”‚ └── logs/ β”‚ └── uploads.log ``` Benefits: - Per-site isolation - Easier debugging - Independent log files - Reduced attack surface --- ## πŸ”§ 2. Create the Security Directory From the site root: ```bash cd /var/www/sites/example-site mkdir .security mkdir .security/logs ``` Set secure permissions: ```bash chown -R root:www-data .security chmod 750 .security chmod 750 .security/logs ``` --- ## πŸ“„ 3. Install the Upload Guard Script Create the script file: ```bash nano .security/upload-logger.php ``` Paste your hardened upload monitoring script. Inside the script, configure logging: ```php $logFile = __DIR__ . '/logs/uploads.log'; ``` Lock the script: ```bash chown root:root .security/upload-logger.php chmod 644 .security/upload-logger.php ``` --- ## βš™οΈ 4. Enable auto_prepend_file (Per Site) ### Option A β€” PHP-FPM Pool (Recommended) Edit the site’s PHP-FPM pool configuration: ```bash nano /etc/php/8.x/fpm/pool.d/example-site.conf ``` Add: ```ini php_admin_value[auto_prepend_file] = /var/www/sites/example-site/.security/upload-logger.php ``` Reload PHP-FPM (adjust service name to match your PHP version): ```bash systemctl reload php8.x-fpm ``` --- ### Option B β€” Apache Virtual Host If using a shared PHP-FPM pool, configure in the vHost: ```apache php_admin_value auto_prepend_file /var/www/sites/example-site/.security/upload-logger.php ``` Reload Apache: ```bash systemctl reload apache2 ``` --- ## 🚫 5. Block Web Access to `.security` Prevent direct HTTP access to the security folder. In the vHost: ```apache Require all denied ``` Or in `.htaccess` (if allowed): ```apache Require all denied ``` --- ## βœ… 6. Verify Installation Create a temporary file: ```php ``` Upload any file and check logs: ```bash cat .security/logs/uploads.log ``` You should see a new entry. --- ## πŸ”’ 8. Disable PHP Execution in Uploads Always block PHP execution in upload directories. Example (Apache): ```apache php_admin_flag engine off AllowOverride None ``` Reload Apache after changes. --- ## πŸ›‘οΈ 9. Enable Blocking Mode (Optional) After monitoring for some time, enable blocking. Edit: ```php $BLOCK_SUSPICIOUS = true; ``` Then reload PHP-FPM. --- ## πŸ“Š 10. (Optional) Fail2Ban Integration (JSON logs) Create a JSON-aware filter that matches `event: "suspicious"` and extracts the IP address. ```bash nano /etc/fail2ban/filter.d/php-upload.conf ``` ```ini [Definition] # Match JSON lines where event == "suspicious" and capture the IPv4 address as failregex = ^.*"event"\s*:\s*"suspicious".*"ip"\s*:\s*"(?P\d{1,3}(?:\.\d{1,3}){3})".*$ ignoreregex = ``` Create a jail that points to the per-site logs (or a central aggregated log): ```ini [php-upload] enabled = true filter = php-upload logpath = /var/www/sites/*/.security/logs/uploads.log maxretry = 3 findtime = 600 bantime = 86400 action = iptables-multiport[name=php-upload, port="http,https", protocol=tcp] ``` Restart Fail2Ban: ```bash systemctl restart fail2ban ``` ### Fail2Ban action: nftables example If your host uses nftables, prefer the `nftables` action so bans use the system firewall: ```ini [php-upload] enabled = true filter = php-upload logpath = /var/www/sites/*/.security/logs/uploads.log maxretry = 3 findtime = 600 bantime = 86400 action = nftables[name=php-upload, port="http,https", protocol=tcp] ``` This uses Fail2Ban's `nftables` action (available on modern distributions). Adjust `port`/`protocol` to match your services. ### Central log aggregation (Filebeat / rsyslog) Forwarding per-site JSON logs to a central collector simplifies alerts and Fail2Ban at scale. Two lightweight options: - Filebeat prospector (send to Logstash/Elasticsearch): ```yaml filebeat.inputs: - type: log paths: - /var/www/sites/*/.security/logs/uploads.log json.keys_under_root: true json.add_error_key: true fields: source: php-upload-logger output.logstash: hosts: ["logserver:5044"] ``` - rsyslog `imfile` forwarding to remote syslog (central rsyslog/logstash): Add to `/etc/rsyslog.d/10-upload-logger.conf`: ```text module(load="imfile" PollingInterval="10") input(type="imfile" File="/var/www/sites/*/.security/logs/uploads.log" Tag="uploadlogger" Severity="info" Facility="local7") *.* @@logserver:514 ``` Both options keep JSON intact for downstream parsing and reduce per-host Fail2Ban complexity. ### Testing your Fail2Ban filter Create a temporary file containing a representative JSON log line emitted by `upload-logger.php` and run `fail2ban-regex` against your filter to validate detection. ```bash # create test file with a suspicious event cat > /tmp/test_upload.log <<'JSON' {"ts":"$(date -u +%Y-%m-%dT%H:%M:%SZ)","event":"suspicious","ip":"1.2.3.4","user":"guest","name":"evil.php.jpg","real_mime":"application/x-php","reasons":["bad_name","php_payload"]} JSON # test the filter (adjust path to filter if different) fail2ban-regex /tmp/test_upload.log /etc/fail2ban/filter.d/php-upload.conf ``` `fail2ban-regex` will report how many matches were found and display sample matched groups (including the captured ``). Use this to iterate on the `failregex` if it doesn't extract the IP as expected. --- ## 🏁 Final Architecture ```text Client β†’ Web Server β†’ PHP (auto_prepend) β†’ Application β†’ Disk ↓ Log / Alert / Ban ``` This provides multi-layer upload monitoring and protection. --- ## πŸ—‚οΈ Log rotation & SELinux/AppArmor notes - Example `logrotate` snippet to rotate per-site logs weekly and keep 8 rotations: ```text /var/www/sites/*/.security/logs/uploads.log { weekly rotate 8 compress missingok notifempty create 0640 root adm } ``` - If your host enforces SELinux or AppArmor, ensure the `.security` directory and log files have the correct context so PHP-FPM can read the script and write logs. For SELinux (RHEL/CentOS) you may need: ```bash chcon -R -t httpd_sys_rw_content_t /var/www/sites/example-site/.security/logs restorecon -R /var/www/sites/example-site/.security ``` Adjust commands to match your platform and policy. AppArmor profiles may require adding paths to the PHP-FPM profile. ## ⚠️ Security Notes - Never use `777` permissions - Keep `.security` owned by `root` - Regularly review logs - Update PHP and extensions - Combine with OS-level auditing for best results --- ## πŸ“Œ Recommended Maintenance Weekly: ```bash grep ALERT .security/logs/uploads.log ```