PHP Safe Mode

PHP's Safe Mode is an attempt to solve at least some of the security problems inherent in access issues by modifying the behavior of applications written in PHP. While it may be wrong-headed to attempt to solve system-level problems at the application level, nevertheless there has been considerable interest in Safe Mode as a possible solution. And so some sysadmins have decided to run PHP in Safe Mode on their own servers. Similarly, some hosts have decided that they will offer PHP only in Safe Mode.

When operating in Safe Mode, PHP allows the owner of a script to operate on only its own files and directories. This restriction does indeed greatly minimize the possibility of PHP's being used to carry out attacks on system integrity, and so Safe Mode is a reasonably attractive alternative for sysadmins who do not want to make the very considerable effort of putting better security restrictions into effect. However, it is at best a kind of band-aid, and so if you need serious levels of security, you should not expect your host's or your own server's Safe Mode to provide it for you.

Please note that as of PHP 5.3.0, PHP's Safe Mode has been deprecated.

How Safe Mode Works

Putting Safe Mode into effect is a simple matter of setting a configuration directive in the Safe Mode section of the Language Options area of a php.ini file: safe_mode TRUE (or on or 1). Of course, you must be a sysadmin or otherwise have access to that file.

Once Safe Mode has been put into effect, PHP performs a UID check on every file operation, determining whether the user ID of a script (denoting its owner) is the same as the user ID of the file or directory where an operation (reading or writing, creating or deleting) is being proposed. If the script owner is not the owner of the file or directory, that operation is disallowed.

Let us imagine that a malicious user jasong has purchased the right to have a website hosted on a shared server. That user is the owner of a directory known conventionally as docroot, where his website files reside, and he creates a script, something like the following (we'll call it innocuous.php), which attempts to read the system password file:

<?php readfile( ‘/etc/password’ ); ?>

Since the /etc/passwd file is, of necessity, readable by all users, a standard PHP engine (where Safe Mode is not in effect) will give the attacker the file. This is not as serious as it may sound, since the system passwords are typically not stored there but rather in /etc/shadow, which is accessible to root only). But the compromised file will still leak a lot of information about your system that should not be public, including what usernames have login shells.

When Safe Mode is in effect, however, typical output from this script would not be the file's contents, but rather something like the following:

Warning: SAFE MODE Restriction in effect.
The script whose uid is 123 is not allowed to access /etc/password
owned by uid 0 in /docroot/innocuous.php on line 1

This message tells us that a script owned by user 123 (that is, jasong) is attempting to access a file owned by user 0 (that is, root), and that the access is being blocked because the respective owners are not the same. In this case, then, turning on Safe Mode has provided a significant level of protection.

An alternative to Safe Mode's rigorous UID check is a GID check, enabled by setting safe_mode_gid on(or true, or 1). This directive relaxes the check, so that it will be satisfied if the GID (group owner) of the script matches that of the file or directory. That way, you can use a team of developers, each with his or her own user ID, but all in the www group.

Other Safe Mode Features

Additional configuration directives control other details of how Safe Mode operates. For full details, you should go to Chapter 42 in the PHP Manual, readily available at http://php.net/features.safe-mode, but we will provide an overview here, along with some discussion of the implications of each directive. In general terms, though, Safe Mode allows you a considerable measure of control over include directories, exec directories, and user-settable environment variables. Here's a short explanation of those other configuration directives.

When a script executed in a Safe Mode environment includes a file from the directory specified by the safe_mode_include_dir directive, the usual user ID (or group ID) restrictions are bypassed, and a script owned by someone else is allowed to be included. This is useful when you need to include libraries (such as PEAR), and a common configuration might be something like safe_mode_include_dir="/usr/local/lib/php/". When specifying paths in Safe Mode directives, it is important to include the trailing slash. Without the slash, the value is treated as a prefix, meaning that /usr/local/lib would match /usr/local/libdneba/ and /usr/local/libchxo/. More than one directory or prefix can be specified using a colon-separated list (semicolon-separated on Windows).

One of the most important Safe Mode features is the ability to strictly control which system files may be executed by PHP scripts. The safe_mode_exec_dir directive allows administrators to specify a directory from which useful binary executables like ImageMagick and aspell may be run, without also allowing PHP scripts to run passwd or other dangerous system utilities. The argument to this directive is the name of a directory, into which you create a symbolic link to any allowed executables. The process would therefore be something like this. First, you create an appropriate entry in php.ini:

safe_mode_exec_dir=‘/bin/safe/’

Next, you create a symbolic link for aspell (for example) in that directory using the ln -s command as root:

# cd /bin/safe
# ln -s /usr/bin/aspell aspell

Finally, in your script, you execute the now-accessible (but otherwise inaccessible) utility:

<?php
  $output = shell_exec( ‘/bin/safe/aspell /var/www/myfiles/document.txt’ );

The final two Safe Mode directives deal with the global environment variables that are available to PHP scripts. These are the variables that show up in a phpinfo() call, system information that really shouldn't be made public. This is the kind of information that makes most sysadmins think that they really shouldn't allow users to call phpinfo() at all. Safe Mode by default makes all of those environment variables off limits to PHP scripts, except for any that begin with the prefix PHP_.

The safe_mode_allowed_env_vars directive allows you to specify prefixes for any other environment variables that you are willing to allow PHP scripts to set and change with the putenv() function (see http://php.net/putenv for more information). Environment variables differ from constants and other global variables in that they are passed to any child processes created by a script, such as with shell_exec() calls.

You might, for example, want to allow applications running on your server (and any underlying processes called by them) access to a special library of functions. You could do that by inserting an instruction like this into php.ini:

safe_mode_allowed_env_vars = ‘SAFELIB_’

A user could now use putenv() to create a usable environmental variable, something like this:

<?php
putenv( ‘SAFELIB_LIBPATH=/usr/lib/mylib’ );

The safe_mode_protected_env_vars directive allows you to fine-tune that list by specifying specific environment variables that can't be changed, even if safe_mode_allowed_env_vars would have permitted it.

Safe Mode Alternatives

We will finally describe briefly two of the key alternatives to Safe Mode's UID check. As alternatives, they are used independently of whether Safe Mode has been enabled (although they are often thought of as being part of Safe Mode, and their directives are located at the end of the Safe Mode section of php.ini).

  • The open_basedir configuration directive sets a directory within which any file that is to be opened must reside. This directive may be set in php.ini, with open_basedir /mybasedir, or in Apache's httpd.conf file, with a directive something like this:
          <Directory /mybasedir>
            php_admin_value open_basedir /mybasedir
          </Directory>
  • When open_basedir has been set, any file that is being opened under PHP's control (with a function like fopen(), for example) must reside in the designated directory; if it does not, the file is not permitted to be opened. In such a case, assuming the same innocuous.php as earlier (jasong's attempt to open the file /etc/password for reading), the script, instead of executing, would return a message something like this:
    Warning: open_basedir restriction in effect. File is in wrong directory in
    /docroot/innocuous.php on line 1
  • The disable_functions and disable_classes directives enable you to restrict users' ability to execute specified functions and classes. These directives must be set in php.ini, not in httpd.conf, with a line such as this:
    disable_functions readfile,system,chmod,chown,uline

Note that multiple entries are permitted, separated with commas.

When a function like readfile has been disabled, the malicious innocuous.php script, instead of executing, would return a message like the following:

Warning: readfile() has been disabled for security reasons in
/docroot/innocuous.php on line 1

Safe Mode, then, and its two alternatives open_basedir and disable_functions or disable_classes, provide a reasonably strong level of security to your server, at very little expense in terms of time and effort to get it set up. It should be a part of every systems administrator's arsenal of security tools. There are no convincing reasons not to be using it.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.198.183