Securing PHP on Debian Linux

NOTE: This document has been superseded by my document about SuPHP.

My friend Theo recently pointed out to me a problem with PHP. Apache runs as www-data (on Debian), which means that PHP when installed as an apache module will also run as this user. This might not immediately appear like a problem. Let me just point out 2 very disconcerting points.

Firstly, the user www-data needs read access to all .php files, meaning one user's php script, can read another users. For example, include('/home/victim/wwwroot/db.inc'); would give you another users database settings! Ok, so the attacker would need to know exactly where the script is, but it's still bad!

The second issue, is that if apache runs as www-data, then the user www-data can kill the processes. This means that somebody using PHP on your server could stop your webserver.

I needed a way to prevent this. This document explains how I have setup PHP on my server to get around these issues.

The first thing I did, was install binfmt-support. This allows you to specify that files with extension .php should be run by php. You'll need the binfmt_misc module loaded into the kernel for this.

Install binfmt, and php4-cgi on your machine as follows

  apt-get install binfmt-support php4-cgi

You'll then want to configure binfmt to run .php files with the php cgi, on debian, this can be done as follows

  update-binfmts --install PHP /usr/bin/php4 --extension php; update-binfmts --install PHP3 /usr/bin/php4 --extension php3; update-binfmts --install PHP4 /usr/bin/php4 --extension php4

If you are not using debian, and the binfmt-support wrapper is not availible, you can use the following method

  cd /proc/sys/fs/binfmt_misc;
  echo ':PHP:E::php::/usr/bin/php4:' > register;
  echo ':PHP3:E::php3::/usr/bin/php4:' > register;
  echo ':PHP4:E::php4::/usr/bin/php4:' > register

Test that it's working now by doing the following.

  echo "" > test.php
  chmod 770 ./test.php
  ./test.php

If all is going well, the PHP should execute, and give you something similar to this….

  X-Powered-By: PHP/4.1.2
  Content-type: text/html
   
  moo

The next step is to setup apache up so that it knows to run .php files as CGI. This is done by adding the following lines to the <Directory /> section in httpd.conf. (you might want to put it elsewhere to be more restrictive, that choice lies with you!)

  Options SymLinksIfOwnerMatch ExecCGI
  AddHandler cgi-script .php .php3 .php4

If your apache install has SuEXEC running (in debian, it will be default), PHP will now run as the user specified in your VirtualHost definitions, on one condition…. SuEXEC is configured at compile time to only run things within /var/www. To get SuEXEC to allow you to store vhosts elsewhere, we need to recompile apache. Debian makes this really easy for us!

Acknowledgements

Theo - Pointed out the obvious problems in the first place

Colin Watson - Creator of the binfmt-support wrapper, contacted me with information on using the wrapper