In association with heise online

PHP via CGI

The CGI solution used by most hosting services is flexible and quite secure if configured correctly. It executes PHP applications as separate processes via the classic CGI mechanism. To prevent scripts from running at full server rather than at user privilege level, providers implement the Apache modules mod_suexec or mod_suphp. This strategy not only protects the server itself but also other users on this server against the consequences of attacks.

In addition, web users can control PHP options within a CGI configuration in numerous ways. This is because in CGI mode, the PHP interpreter gives precedence to a php.ini file which is situated in the same directory as the PHP script being executed.

Unlike .htaccess files, however, a php.ini file doesn't apply to subdirectories. Therefore, every directory containing directly executable PHP scripts needs to contain its own php.ini file. This isn't required for content-restricted include directories for example the wp-content folder of the Wordpress blog system. When in doubt, however, it is advisable to place a copy of php.ini in every directory. Where manual copying involves too much effort, the small Perl script ftp_spread.pl can help. It copies a specified file into every subdirectory of a FTP path given on the command line.

Security relevant PHP options

Before we start creating a suitable php.ini file, let's summarise the most important PHP security options:

  • allow_url_fopen (recommended: off) controls whether or not PHP's file access functions can also access external URLs. When this is prohibited, it is harder for an attacker to remotely inject malicious code. Since PHP 5.2.0, allow_url_include separately controls the behaviour of include() and require().
  • display_errors (recommended: off) switches the display of PHP error messages on or off. While this is helpful for debugging it can also supply attackers with information about internal application details which may faciliate further attacks.
  • disable_functions specifies a list of disabled PHP functions. PHP applications which have been developed with safety in mind avoid potentially harmful functions like exec(); therefore, it isn't a problem for them if this function is disabled - but it is a problem for many of the exploits in circulation.
  • open_basedir (recommended: Web home) limits PHP file operations to the specified directory and its subdirectories. You can include more than one directory if you separate their names by colons. It is important to complete each path name with a slash, as otherwise any directories which happen to begin with the specified name will be included.
  • register_globals (recommended: off) determines whether parameters from URLs or POST data are submitted to scripts as global variables. Many vulnerabilities in PHP applications can only be exploited if this is the case.
  • safe_mode (recommended: on) specifies whether PHP runs in a special safe mode or not. This mode has numerous effects; it causes, for example, an additional UID check for file operations and restricts access to environment variables. It is not included in PHP6 as the PHP developers are of the opinion that its functions are not within the requirements of a scripting language. It is well documented on the PHP page [3].
  • sql.safe_mode determines whether login requests are handled in a special way for database servers. In this mode, PHP functions exclusively use the script owner's system user name for logging into the database. As the name of the database user hardly ever corresponds to that of the system user in shared web hosting environments, this option is only used in very specific conditions.

Given these considerations, a tightly sealed php.ini would therefore include the following:

[PHP]
register_globals = off
allow_url_fopen = off
safe_mode = on
open_basedir = <path name of web directory>
disable_functions = exec,system,passthru,shell_exec,popen,escapeshellcmd,proc_open,proc_nice,ini_restore
display_errors = off

Some of these options require further adjustment. For open_basedir you need to include the path to the web root, which can, for example, be found in the PHP variable DOCUMENT_ROOT returned by phpinfo(). If you have several applications with their own php.ini files in various different subdirectories it is advisable to include the respective base paths for each of the web applications individually.

Print Version | Permalink: http://h-online.com/-747215
  • Twitter
  • Facebook
  • submit to slashdot
  • StumbleUpon
  • submit to reddit
 


  • July's Community Calendar





The H Open

The H Security

The H Developer

The H Internet Toolkit