Securing a PHP Installation

03/29/2001
 

In this article we're going to discuss security issues relating to PHP. PHP can be a very powerful and, overall, secure language. That doesn't mean you can just throw caution to the wind, however.

 

Since PHP is most commonly used as an Apache module, it derives its security model to a large degree from Apache, which, if configured properly, is a very secure environment. In cases where PHP is used as a CGI, this benefit is lost.

 

While considering security, it is wise to also consider the needs of the developer. I have a friend who likes to say that the only secure computer is one unplugged from the network ... and the wall. I know some systems administrators who feel the same way about a web server. They get so zealous about security (and rightly so) that they virtually make the system unusable.

This article is generally OS neutral. What applies to Unix here should apply to Windows as well.

Also in PHP Admin Basics:

Common PHP Installation Problems

Installing PHP as an Apache DSO

PHP Configuration Directives

The PHP Configuration File

Installing PHP on a Windows System

Now let's get down to business.

As an Apache module

If you run PHP as an Apache module, then for the most part everything should be fine, since your Apache server probably runs as a trusted user, usually "nobody" or "www." If you're running Apache as "root," then -- well, don't. The reason is that since root is God on your machine, you don't want something like Apache to have that kind of power. Especially when PHP comes into the picture. Imagine having a nefarious (or stupid) user completely wiping out most of your files because he had the ability to execute rm -rf /*.* through a web page.

Quite often PHP is used in a virtual hosted environment with multiple domains and multiple users per domain. One problem that can happen in this environment is a nosey virtual domain user writing a PHP script to go snooping around other people's files. This could easily be done using the following simple script:

<?php
  /*
   * Assume document root is /usr/local/websites/mydomain
   */

  $location = '../';	// Move up one directory
  $parent = dir($location);
		
  // List the contents of the current directory
  // i.e.: /usr/local/websites
  while($entry = $parent->read()) {
    echo $entry . '<br>';
  }
  $parent->close();
?>

Now a user running this script can see all other virtual domain directories and, with a simple modification of $location, can browse through them, looking at all the files contained therein. To remedy this privacy fiasco waiting to happen, take a look at the php.ini file and specifically the safe_mode, doc_root, and usr_dir directives. By turning on safe_mode and defining doc_root and user_dir, you can eliminate said nosey user problem by restricting him to files contained in his virtual host document root. The following is an example of how the php.ini file might look for these three directives:

safe_mode = On
doc_root = /usr/local/apache/htdocs
user_dir = /home/jdoe/htdocs

As a CGI

Running PHP as a CGI can be a whole new ball game. Because the CGI binary isn't compiled within Apache, it runs under a separate process and user. If you're not careful, it is possible to give away information that you wouldn't want given away.

The first thing you should do is place your CGI binary (php.cgi in most cases) in a location that is outside of your main web tree. If the binary is in a location such as /usr/local/bin, you greatly reduce the risk of giving some script-kiddie the ability to look at otherwise secure files (/etc/passwd is one that comes to mind). The biggest downside to placing your binary outside of the web tree is that then all of your scripts must have the following line at the top of the page:

#!/usr/local/bin/php

You'll also want to enable safe mode in the php.ini file. As with the Apache module, this restricts certain functions in PHP based on file ownership or directory location. With safe mode turned on, you're taking a proactive measure with security by defining from the start how you want PHP to behave.

Some of the most common attacks come in the form of obtaining access to files that should otherwise be hidden. Taking the above measures should go a long way to prevent this.

One way to prevent the user from calling the CGI binary directly is to force a CGI redirect within Apache. To do this, just add the following directives in Apache's httpd.conf file:

Action php-script /cgi-bin/php.cgi
AddHandler php-script .php

This will rewrite the following URL:

	http;//example.com/mywebdir/test.htm

into:

	http://example.com/cgi-bin/php/mywebdir/test.htm

and perform permission checks on the mywebdir/ directory in the process. This also has the added benefit of making the URL a little shorter, though security-wise, a bad guy could just as easily call the latter URL (and any other document that you probably don't want him seeing). For this reason you should compile your PHP CGI binary with the following configure option:

--enable-force-cgi-redirect

And again, set your doc_root and user_dir options in the php.ini. You won't regret it!

Summary

Throughout this article we've covered how to evaluate your needs while considering issues of security. We've also covered security issues specific to the use of PHP and what you should be aware of when configuring PHP. For more information on PHP security, take a look at Chapter 4. Security of the online PHP manual. I hope this points you in the right direction to building a successful web server.

Darrell Brogdon is a web developer for SourceForge at VA Linux Systems and has been using PHP since 1996.


Read more PHP Admin Basics columns.

Return to the PHP DevCenter.