phpHarden in Action: Real-World PHP Security Checklist

Migrating to phpHarden: Step-by-Step Hardening for PHP ProjectsMigrating an existing PHP project to a hardened environment can dramatically reduce attack surface, stop common exploit vectors, and improve overall system stability. phpHarden is a focused approach and toolset for applying practical, repeatable hardening measures to PHP installations, codebases, and deployment pipelines. This guide walks you through a step-by-step migration: assessing your current state, planning the migration, applying configuration and code changes, testing, and deploying with ongoing maintenance.


1. Why Harden PHP?

PHP powers a large portion of the web, which makes it a frequent target for attackers. Common vulnerabilities include remote code execution, insecure deserialization, file inclusion flaws, and misconfigurations that expose debugging info or enable dangerous functions. Hardening reduces risk by:

  • Removing or restricting risky functionality
  • Limiting file system and network access
  • Applying strict configuration defaults
  • Enforcing secure coding and dependency management

2. Preliminary Assessment

Before making changes, create a clear baseline.

  • Inventory: list PHP versions in use, frameworks (Laravel, Symfony, WordPress), and extensions.
  • Configuration snapshot: php.ini, .user.ini files, and environment-specific overrides.
  • Dependency audit: Composer packages and their known vulnerabilities (use tools like Composer Audit or Snyk).
  • Operational constraints: hosting type (shared, VPS, container), CI/CD pipeline, and rollback plan.
  • Backup plan: full backups of application, database, and configuration.

Document findings in a migration plan that prioritizes production safety: test/staging rollouts, maintenance windows, and monitoring.


3. Versioning and Compatibility

  • Upgrade to a supported PHP version. Use the latest stable PHP release supported by your frameworks to receive security fixes and performance improvements.
  • Check for deprecations and incompatible APIs between your current PHP version and the target. Use static analysis tools (PHPStan, Psalm) and run test suites to find breaking changes.
  • If you rely on specific PHP extensions, confirm their availability and compatibility on the target version.

4. Configuration Hardening (php.ini and Beyond)

Key php.ini settings to change or verify:

  • Disable display_errors in production:
    • display_errors = Off
  • Log errors to a file instead of sending them to the client:
    • error_log = /var/log/php_errors.log
  • Disable dangerous functions:
    • disable_functions = exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec,show_source
      Only enable what you absolutely need; document exceptions.
  • Restrict file uploads and execution:
    • file_uploads = On (if needed)
    • upload_max_filesize and post_max_size — set conservative limits
  • Limit resource usage:
    • memory_limit — set per-app reasonable cap
    • max_execution_time — keep short for web requests
  • Restrict open_basedir to limit file system access to necessary paths:
    • open_basedir = /var/www/html:/tmp
  • Disable allow_url_fopen and allow_url_include unless explicitly required:
    • allow_url_fopen = Off
    • allow_url_include = Off
  • Session hardening:
    • session.cookie_httponly = 1
    • session.cookie_secure = 1 (when using HTTPS)
    • session.use_strict_mode = 1
  • OPcache configuration: enable for performance but secure settings:
    • opcache.validate_timestamps = 1 (0 in immutable deployments)
    • opcache.revalidate_freq = 2

If using per-directory .user.ini files or environment-based overrides, ensure they cannot re-enable dangerous settings.


5. Environment & Deployment Changes

  • Run PHP in FPM with dedicated pools per app or per user to isolate processes and permissions.
  • Use strong user separation; do not run web server/PHP as root.
  • Use containerization (Docker) or immutable images to lock runtime configuration.
  • Ensure file permissions: web files should be owned by a deploy user and writable only where necessary (uploads/temp). Avoid 777.
  • Limit network egress from application hosts; only allow required destinations (APIs, package registries).
  • Use a WAF for additional protection against common web attacks while you harden the app.

6. Codebase Hardening

  • Input validation and output encoding: centralize validation, use prepared statements/ORM to prevent SQL injection, and escape output to prevent XSS.
  • Remove dangerous dynamic code evaluation (eval(), create_function(), dynamic includes). Replace with safe alternatives.
  • Avoid insecure unserialize() calls; prefer json_decode() for structured data. If unserialize is unavoidable, use allowed_classes option.
  • Apply the Principle of Least Privilege in code: avoid global state, restrict features to authenticated/authorized users.
  • Implement CSRF tokens and proper authentication session handling.
  • Sanitize file uploads: validate MIME types, use randomized filenames, store outside webroot, and scan for malware.
  • Use typed properties and return types where possible to reduce class/interface misuse.

7. Dependency & Package Management

  • Use Composer with strict version constraints and lock files (composer.lock).
  • Regularly run composer audit and subscribe to vulnerability feeds (e.g., GitHub Dependabot, Snyk).
  • Avoid pulling code at runtime. Cache dependencies in builds and deploy immutable artifacts.
  • Replace unmaintained packages with maintained alternatives.

8. Automated Scanning & Testing

  • Static analysis: integrate PHPStan/PSalm in CI to find type and code issues.
  • SAST and dependency scanning: run tools that detect common vulnerabilities and unsafe patterns.
  • Dynamic testing: run automated integration and functional tests; use tools like OWASP ZAP for automated web scanning.
  • Fuzz testing for input handling code where feasible.

9. Monitoring, Logging & Incident Response

  • Centralize logs (errors, access, security events) and monitor for anomalies.
  • Configure alerting for critical issues (e.g., new PHP errors spike, failed logins).
  • Keep an incident response playbook: rollback steps, forensic data capture, and notification procedures.
  • Periodically review logs for evidence of attempted exploitation after migration.

10. Rollout Strategy

  • Start in a staging environment that mirrors production.
  • Use feature flags or phased rollout (canary) to limit exposure.
  • Verify behavior under load and run regression tests.
  • Schedule maintenance windows for production changes, with backups and rollback plans.

11. Post-Migration Checklist

  • Confirm PHP version and configuration: php -v and phpinfo() (restricted).
  • Verify disable_functions, allow_url_fopen/include, open_basedir, and session settings.
  • Run your test suite and static analysis tools.
  • Confirm file permissions and FPM pool user settings.
  • Validate logs route to the central logging system and alerts work.
  • Run security scans (SCA/SAST/DAST) and resolve high/critical findings.

12. Ongoing Maintenance

Hardening is not a one-time task. Maintain security by:

  • Applying PHP security updates promptly.
  • Regularly auditing composer dependencies.
  • Re-running static and dynamic scans in CI.
  • Reviewing server configurations after platform changes.
  • Conducting periodic penetration tests.

13. Common Migration Pitfalls

  • Breaking backwards compatibility due to PHP version changes — mitigate with tests and code fixes.
  • Overrestrictive enable/disable of functions that break legitimate features — document and test exceptions.
  • Relying solely on perimeter defenses (WAF/CDN) without fixing application-level issues.
  • Weak file permission and deployment practices that reintroduce vulnerability.

14. Example: Minimal php.ini Hardening Snippet

display_errors = Off log_errors = On error_log = /var/log/php_errors.log memory_limit = 256M max_execution_time = 30 upload_max_filesize = 10M post_max_size = 12M allow_url_fopen = Off allow_url_include = Off disable_functions = exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec,show_source open_basedir = /var/www/html:/tmp session.cookie_httponly = 1 session.cookie_secure = 1 session.use_strict_mode = 1 

15. Conclusion

Migrating to phpHarden involves a mix of configuration, code changes, deployment practices, and ongoing processes. The most effective migrations are incremental, well-tested, and supported by CI/CD automation and monitoring. By applying the steps above you can significantly reduce attack surface and improve the security posture of your PHP projects.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *