Files
UploadShied/docs/INSTALLATION.md

7.3 KiB
Raw Blame History

Installation & Production Deployment Guide

This guide shows a minimal, secure installation and rollout path for UploadShield's primary script (uploadshield.php). Follow these steps in a staging environment first; do not enable blocking until detectors are tuned.

Prerequisites

  • A Linux host running PHP-FPM (PHP 8.0+ recommended).
  • composer available for dev tasks.
  • SSH/privileged access to configure the site pool and run provisioning scripts.

Quick overview

  1. Place uploadshield.php in a secure per-site folder (recommended .security).
  2. Create logs/, quarantine/, state/ and set strict ownership and permissions.
  3. Configure uploadshield.json for your environment; keep ops.block_suspicious off for initial tuning.
  4. Enable auto_prepend_file in the site PHP-FPM pool to run the logger before application code.
  5. Verify logging, tune detectors, deploy log rotation, and enable alerting.

1. Clone & dependencies (developer workstation)

  • Clone the repository and install dev deps (for tests/static analysis):
git clone <repo-url> /srv/uploadshield
cd /srv/uploadshield
composer install --no-interaction --prefer-dist

Run tests locally:

vendor/bin/phpunit --configuration phpunit.xml
vendor/bin/phpstan analyse -c phpstan.neon

2. Recommended file layout (per-site) Use a hidden per-site security folder so uploadshield.php is not web-accessible.

Example layout:

/var/www/sites/example-site/
├── public/
├── app/
├── uploads/
├── .security/
│   ├── uploadshield.php
│   └── logs/
│       └── uploads.log
├── quarantine/
└── state/
 Place `uploadshield.php` into `.security/uploadshield.php`.

**3. Copy files & configure**
- Place `uploadshield.php` into `.security/uploadshield.php`.
- Copy `uploadshield.json` from the repository to the same directory and edit paths to absolute values, e.g.:
  - `paths.log_file` → `/var/www/sites/example-site/.security/logs/uploads.log`
  - `paths.quarantine_dir` → `/var/www/sites/example-site/quarantine`
  - `paths.state_dir` → `/var/www/sites/example-site/state`
- Ensure `ops.block_suspicious` is `false` initially (observe mode).

**4. Create directories & set permissions (run as root)**
Adjust user/group to your site environment (`www-data` used in examples):

```bash
# example: run on target host as root
mkdir -p /var/www/sites/example-site/.security/logs
mkdir -p /var/www/sites/example-site/quarantine
mkdir -p /var/www/sites/example-site/state
chown -R root:www-data /var/www/sites/example-site/.security
chmod 750 /var/www/sites/example-site/.security
chmod 750 /var/www/sites/example-site/.security/logs
# quarantine must be restrictive
chown -R root:www-data /var/www/sites/example-site/quarantine
chmod 0700 /var/www/sites/example-site/quarantine
# state directory writable by PHP-FPM if required (group-write)
chown -R root:www-data /var/www/sites/example-site/state
chmod 0750 /var/www/sites/example-site/state
# ensure log file exists with safe perms
touch /var/www/sites/example-site/.security/logs/uploads.log
chown root:www-data /var/www/sites/example-site/.security/logs/uploads.log
chmod 0640 /var/www/sites/example-site/.security/logs/uploads.log

Alternatively use the included provisioning scripts on the host:

  • scripts/provision_dirs.sh — run as root; idempotent and attempts to set SELinux fcontext.
  • scripts/ansible/uploadshield-provision.yml — Ansible playbook for bulk provisioning.

5. PHPFPM configuration (per-site pool) Edit the site's FPM pool (example: /etc/php/8.1/fpm/pool.d/example-site.conf) and add: php_admin_value[auto_prepend_file] = /var/www/sites/example-site/.security/uploadshield.php

; Ensure uploadshield runs before application code
php_admin_value[auto_prepend_file] = /var/www/sites/example-site/.security/uploadshield.php

Then reload PHP-FPM:

sudo systemctl reload php8.1-fpm

Notes:

  • Use the absolute path to uploadshield.php.
  • If your host uses a shared PHP-FPM pool, consider enabling per-vhost auto_prepend_file via nginx/apache or create a dedicated pool for the site.

6. Log rotation Create /etc/logrotate.d/uploadshield with content adapted to your paths:

/var/www/sites/example-site/.security/logs/uploads.log {
    rotate 7
    size 10M
    compress
    missingok
    notifempty
    copytruncate
    create 0640 root www-data
    sharedscripts
    postrotate
        if systemctl is-active --quiet php8.1-fpm; then
            systemctl reload php8.1-fpm >/dev/null 2>&1 || true
        fi
    endscript
}

copytruncate is safe and avoids needing to stop PHP; alternatively use postrotate to reload FPM.

7. Verify installation (smoke tests)

  • Upload a benign file via your app or via a simple test form and confirm a JSON upload line appears in the log.
  • Upload a file containing <?php to confirm detectors log suspicious_upload entries.
  • Check logs/uploads.log for events.

php -S 127.0.0.1:8000 -t . -d auto_prepend_file=/var/www/sites/example-site/.security/uploadshield.php

# from site root
php -S 127.0.0.1:8000 -t . -d auto_prepend_file=/var/www/sites/example-site/.security/uploadshield.php
# then curl a file POST to your test endpoint
curl -F "file=@/path/to/sample.txt" http://127.0.0.1:8000/upload_test.php

8. Tuning & staging

  • Keep ops.block_suspicious set to false while monitoring logs and tuning:
    • allowlists.base64_uris — add URIs for trusted base64 endpoints.
    • allowlists.ctypes — add trusted content-types such as image/svg+xml if needed.
    • limits.sniff_max_bytes / limits.sniff_max_filesize — tune scanning cost vs coverage.
  • Run the system under representative traffic and check for false positives.

9. Gradual enable blocking

  • After tuning, enable blocking in a controlled manner:
    1. Set ops.block_suspicioustrue in uploadshield.json on a small subset of sites or a canary host.
    2. Monitor errors, rollback quickly if issues appear.
    3. Gradually roll out to remaining hosts.

10. Monitoring & alerting

  • Forward logs/uploads.log to your SIEM or log aggregator (Filebeat/Fluentd).
  • Create alerts for event == suspicious_upload or event == raw_body and for rapid flood counts.
  • Monitor disk usage for logs/ and ensure logrotate is active.

11. Security & operational checklist

  • Ensure quarantine/ and .security/logs are not accessible from the web server.
  • Verify SELinux/AppArmor contexts after running provisioning.
  • Ensure owner/group are set to root and web group (e.g., root:www-data) and modes match the guide. Keep uploadshield.php readable by root (644) and the logs readable only by the intended group (640).

Rollback

  • Disable php_admin_value[auto_prepend_file] in the pool and reload PHP-FPM.
  • Remove or rotate the uploadshield files if needed.

Further reading & files

  • Integration notes: INTEGRATION.md
  • Provisioning script: scripts/provision_dirs.sh
  • Ansible playbook: scripts/ansible/uploadshield-provision.yml
  • Example configuration: uploadshield.json

If you want, I can: (a) generate a site-specific copy of these snippets for your exact paths/PHP version, (b) open a PR with the updated documentation, or (c) produce a one-command installer playbook that runs the provisioning and copies files to a remote host. Tell me which option you prefer.