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