Files
UploadShied/INTEGRATION.md

4.3 KiB

Integration & Tuning

This document complements the installation steps in docs/INSTALLATION.md by focusing on detector tuning, allowlists, and advanced integrations (log forwarding, Fail2Ban, etc.).

Example uploadshield.json (simplified) for UploadShield:

{
    "modules": {
        "flood": true,
        "filename": true,
        "mime_sniff": true,
        "hashing": true,
        "base64_detection": true,
        "raw_peek": false,
        "archive_inspect": true,
        "quarantine": true
    },
    "paths": {
        "log_file": "logs/uploads.log",
        "quarantine_dir": "quarantine",
        "state_dir": "state",
        "allowlist_file": "allowlist.json"
    },
    "limits": {
        "max_size": 52428800,
        "raw_body_min": 512000,
        "sniff_max_bytes": 8192,
        "sniff_max_filesize": 2097152
    },
    "ops": {
        "quarantine_owner": "root",
        "quarantine_group": "www-data",
        "quarantine_dir_perms": "0700",
        "block_suspicious": false
    },
    "allowlists": {
        "base64_uris": [
            "/api/uploads/avatars",
            "#/hooks/(github|gitlab|stripe|slack)#"
        ],
        "ctypes": ["image/svg+xml","application/xml","text/xml"]
    }
}

Notes:

  • Remove the // comments if copying from examples. Use absolute paths in production where possible.

Content detector tuning

  • The ContentDetector performs a fast head-scan to detect PHP open-tags and common webshell indicators (e.g., passthru, system, exec, base64_decode, eval, assert).
  • Tuning options (in uploadshield.json):
    • limits.sniff_max_bytes (default 8192) — how many bytes to scan from the file head.
    • limits.sniff_max_filesize (default 2097152) — only scan files up to this size.
    • detectors.content.allow_xml_eval — relax eval() detection for XML/SVG when appropriate.

False positives

  • eval( appears in benign contexts (SVG/JS). To reduce false positives:
    • Add trusted URIs to allowlists.base64_uris.
    • Add trusted content-types to allowlists.ctypes.
    • Tune scan size limits.

Allowlists

  • allowlists.base64_uris: URI patterns (substring or PCRE when wrapped with #) that should bypass base64/raw detection.
  • allowlists.ctypes: content-types to treat as permitted for encoded payloads (e.g., image/svg+xml).

Archive inspection & quarantine

  • Archives uploaded are flagged and—if quarantine is enabled—moved to the quarantine directory for inspection.
  • Quarantine should be owner root, group www-data, mode 0700. Files inside should be 0600.

Fail2Ban integration (example)

Create a Fail2Ban filter that matches suspicious JSON log lines and captures the IP as <HOST>.

Filter (/etc/fail2ban/filter.d/php-upload.conf):

[Definition]
failregex = ^.*"event"\s*:\s*"suspicious".*"ip"\s*:\s*"(?P<host>\d{1,3}(?:\.\d{1,3}){3})".*$
ignoreregex =

Jail example (adjust logpath):

[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]

Test with fail2ban-regex using a representative JSON log line.

Central log aggregation (Filebeat / rsyslog)

Forward JSON logs to your aggregator to centralize alerts and analysis. Example Filebeat input:

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-uploadshield
output.logstash:
    hosts: ["logserver:5044"]

Logrotate & SELinux notes

Per-site logrotate snippets are included in examples/logrotate.d/uploadshield. Use copytruncate or reload PHP-FPM after rotation.

If SELinux is enabled, the provisioning script attempts to register fcontexts and run restorecon. Verify contexts manually as needed.

Final notes

  • Use observe mode (ops.block_suspicious: false) while tuning.
  • After tuning, enable blocking in a controlled rollout (canary hosts first).
  • Keep uploadshield.php and .security owned by root and ensure logs and quarantine are not web-accessible.

For installation steps and per-site configuration, see docs/INSTALLATION.md.