Team LiB
Previous Section Next Section

3.3. Advanced PHP Hardening

When every little bit of additional security counts, you can resort to modifying PHP. In this section, I present two approaches: one that uses PHP extension capabilities to change its behavior without changing the source code, and another that goes all the way and modifies the PHP source code to add an additional security layer.

3.3.1. PHP 5 SAPI Input Hooks

In PHP, S API stands for Server Abstraction Application Programming Interface and is a part of PHP that connects the engine with the environment it is running in. One SAPI is used when PHP is running as an Apache module, a second when running as a CGI script, and a third when running from the command line. Of interest to us are the three input callback hooks that allow changes to be made to the way PHP handles script input data:


input_filter

Called before each script parameter is added to the list of parameters. The hook is given an opportunity to modify the value of the parameter and to accept or refuse its addition to the list.


treat_data

Called to parse and transform script parameters from their raw format into individual parameters with names and values.


default_post_reader

Called to handle a POST request that does not have a handler associated with it.

The input_filter hook is the most useful of all three. A new implementation of this hook can be added through a custom PHP extension and registered with the engine using the sapi_register_input_filter( ) function. The PHP 5 distribution comes with an input filter example (the file README.input_filter also available at http://cvs.php.net/co.php/php-src/README.input_filter), which is designed to strip all HTML markup (using the strip_tags( ) function) from script parameters. You can use this file as a starting point for your own extension.

A similar solution can be implemented without resorting to writing native PHP extensions. Using the auto_prepend_file configuration option to prepend input sanitization code for every script that is executed will have similar results in most cases. However, only the direct, native-code approach works in the following situations:

  • If you want to enforce a strong site-wide policy that cannot be avoided

  • If the operations you want to perform are too slow to be implemented in PHP itself

  • When the operations simply require direct access to the PHP engine

3.3.2. Hardened-PHP

Hardened-PHP (http://www.hardened-php.net) is a project that has a goal of remedying some of the shortcomings present in the mainstream PHP distribution. It's a young and promising project led by Stefan Esser. At the time of this writing the author was offering support for the latest releases in both PHP branches (4.x and 5.x). Here are some of the features this patch offers:

  • An input filter hook ported to 4.x from PHP 5

  • An extension (called varfilter) that takes advantage of the input filter hook and performs checks and enforces limits on script variables: maximum variable name length, maximum variable value length, maximum number of variables, and maximum number of dimensions in array variables

  • Increased resistance to buffer overflow attacks

  • Increased resistance to format string attacks

  • Support for syslog (to report detected attacks)

  • Prevention of code execution exploits by detecting and rejecting cases where attempts are made to include remote files (via include( ) or require( )) or files that have just been uploaded

  • Prevention of null byte attacks in include operations

Patches to the mainstream distributions can be difficult to justify. Unlike the real thing, which is tested by many users, patched versions may contain not widely known flaws. To be safe, you should at least read the patch code casually to see if you are confident in applying it to your system. Hopefully, some of the features provided by this patch will make it back into the main branch. The best feature of the patch is the additional protection against remote code execution. If you are in a situation where you cannot disable remote code inclusion (via allow_url_fopen), consider using this patch.

    Team LiB
    Previous Section Next Section