PHP applications have a reputation for higher than average security problems. What configuration techniques do you use for making sure the application is secure as possible?

I'm looking for ideas like:

  • Using Hardened PHP/Suhosin
  • Using mod_security
  • Disabling register_globals and allow_url_fopen in php.ini

I normally use Linux, but feel free to suggest Windows solutions too.


  1. Use the open_basedir directive to confine your PHP scripts to their home directory and eventual extra application directories. This is very efficient by itself.

  2. Use hardened php because that costs nothing and it can help.

  3. Use suPHP to have PHP scripts execute as the owner of the file (one user per website) and avoid using files with bad permissions such as 777... suPHP can also allow you to have on php.ini per website so that one site's stupid requirement don't destroy everything.

  4. Mod_security is a big plus but needs to be well used and configured.


In my experience, most vulnerabilities on a PHP-based web site are the result of poor (site) design, rather than flaws in PHP itself.

Some quick tips:

  • Universally filter input, escape output. Clarificaiton: filter doesn't mean escape, it means "if I find something fishy in this user input, cause the submission to fail and tell the user to reformat."
  • Rather than using escapeshellcmd(), simply don't allow any user input to be executed in the shell. That's dangerous and probably never actually necessary.
  • Don't call functions like phpinfo() on a production site (or if you do, see below*).
  • When designing a web application, always consider "is this a possible attack vector?" Say, SQL injection. If the answer is "yes," plug it immediately--don't say "ok, I'll add that later in development as a feature." Security is never a feature.
  • Never output raw errors to the user; this means setting php.ini's display_errors = Off, log_errors = On. Trap run-time errors and output something pretty. Take Twitter's whale as an example: it won't give the user debug-level information, it just says "woops, something broke, please refresh".

*You might also take a peek at a short post I wrote called "Securing phpinfo(), sort of" and be sure to read the comments http://egovsergo.com/2009/04/03/protecting-your-phpinfo/ It was a quick idea I had to (somewhat) protect phpinfo() if I somehow forgot to remove it on a production site.

In a more general way, some developers write wrappers for sensitive functions which check whether not the "production site" flag is set or not, and disables the sensitive function in production.


Other parameters that should be altered to harden the PHP:

safe_mode = Off
register_globals = Off
expose_php = Off
allow_url_fopen = Off
allow_url_include = Off
log_errors = On
error_log = /var/log/phperror.log
display_errors = Off
enable_dl = Off
disable_functions="popen,exec,system,passthru,proc_open,shell_exec,show_source,phpinfo"

Store all PHP errors in file /var/log/phperror.log:

touch /var/log/phperror.log
chmod 666 /var/log/phperror.log

I've added the dotdeb repositories to my /etc/apt/sources.lst

deb http://packages.dotdeb.org stable all
deb-src http://packages.dotdeb.org stable all

As they patch php / apache / mysql much more frequently than Debian does.


Consider setting up open_basedir on a "per site" basis. open_basedir is a php.ini setting which will prevent your scripts from accessing files outside of a defined white list. If your server hosts several sites, it'll prevent one site from reading the database settings from another site. It'll also prevent a php script from accessing/modifying core system files. Open basedir is easy to set up, just add the line "php_admin_value open_basedir /my/list/of/folders:/as/a/colon/seperated/list" to each Apache vhost.

Also consider turning off the PHP script engine for all sites/folders which shouldn't contain PHP scripts (e.g. an uploaded images folder). Again, this is simple, add "php_admin_value engine off" to any Apache VirtualHosts not needing php. To disable PHP in a directory, put the same thing into a Directory tag.

Run file permissions as tight as possible, avoid write access to PHP scripts for the Apache user, this prevents a running script from modifying itself or other scripts on the same site/server. Avoid 777 permissions if at all possible, figure out the minimum permissions required to run the application and use those.

If you're hosting multiple sites, each with their own database, use a seperate MySQL/Postgres user for each, and set permissions on each user such that they only have access to the relevant databases. Again this will prevent a rogue script from tampering with another application's database.

Suosin, HardenedPHP, mod_security and the like are all valuable as well, but use them in addition to a tightly locked down configuration, not instead of.