Wednesday, 2 May 2012

Security Related Directives in php.ini (for Pen Testers and Devs)

For those of you not overly familiar with PHP; php.ini is where you define your settings. As a penetration tester, you should be used to seeing the symptoms of these settings either not being set or being misconfigured. This post aims to pin-point the directives that developers should be familiar with and also show penetration testers the nuts and bolts of the issues they’re seeing so that they may better advise their clients. Feel free to post any more detail or additional directives that you believe should be included.


The disable_functions directive is very important, as it controls which functions are available to be used or abused. When designing an application, if it does not require high risk functions such as eval(), passthru() and system(), etc. then these functions should be disabled. The disable_functions  directive is not affected by Safe Mode however, only internal functions can be disabled using this directive. User-defined functions are unaffected.


Enabling open_basedir will restrict file access to a specifically defined directory. All file operations will then be limited to what has been specified. It is recommended that any file operations should be located within a certain set of directories. If this is implemented, standard canonicalization for directory traversal e.g. “../../../../etc/passwd” will not work. This directive is not affected by Safe Mode being turned on or off.

When a script tries to open a file with, for example, fopen() or gzopen(), the location of the file is checked. When the file is outside the specified directory-tree, PHP will refuse to open it. All symbolic links are resolved, so it's not possible to avoid this restriction with a symlink. If the file doesn't exist then the symlink couldn't be resolved and the filename is compared to (a resolved) open_basedir .

The special value ‘.’ indicates that the working directory of the script will be used as the base-directory. This is, however, a little dangerous as the working directory of the script can easily be changed with chdir().

In httpd.conf, open_basedir can be turned off (e.g. for some virtual hosts) the same way as any other configuration directive with "php_admin_value open_basedir none".
Under Windows, separate the directories with a semicolon. On all other systems, separate the directories with a colon. As an Apache module, open_basedir paths from parent directories are now automatically inherited. The restriction specified with open_basedir is a directory name since PHP 5.2.16 and 5.3.4. Previous versions used it as a prefix. This means that "open_basedir = /dir/incl" also allowed access to "/dir/include" and "/dir/incls" if they exist. When you want to restrict access to only the specified directory, end with a slash. For example: 

open_basedir = /dir/incl/

The default is to allow all files to be opened.


Setting this configuration to off will remove the PHP banner that displays in the server header’s response. This is one layer of defence that will obscure the fact that you’re using PHP (by banner grabbing at least) and moreover the version that is being used and is a good defence-in-depth technique.


This directive is designed to prevent remote file inclusion vulnerabilities from working. An example of this would be if the $absolute_path variable in the following code example were set to a value; the exploit would fail because allow_url_fopen was set.

include ($absolute_path.’inc/’);


The display_errors directive is a simple but important setting that enables detailed errors to the user on an exception. This setting should always be switched off in a production environment.


Enabling safe-mode in PHP allows strict file access permissions. This is done by checking the permissions of the owner of the PHP script that is running against any file access that the script attempts. Should the permissions not match, PHP throws  a security exception. Safe_mode is commonly used by ISPs, so that multiple users can develop their own PHP scripts without risking the integrity of the server.


When enabled, register_globals injects user created scripts with various variables, such as request variables from HTML forms. This functionality coupled with the fact that PHP doesn't require variable initialization means writing insecure code is much easier. A controversial change in PHP after version 4.2.0 was the setting of register_globals to OFF rather than ON. Reliance on this directive was quite common and many people didn't even know it existed and assumed it's just how PHP works. Many users of PHP didn’t understand how this directive worked as it was always on by default and was assumed the inherent behaviour of PHP on the whole. Even though this was a difficult decision, the PHP community decided to disable this directive by default. When enabled, developers use variables yet really don't know for sure where they are generated and often only assume. Internal variables that are defined in the script itself get mixed up with request data sent by users and disabling register_globals changes this.

NB – register_globals has been deprecated as of PHP 5.3.0 and removed as of PHP 5.4.0.


The settings within php.ini are not a fix-all by any means, but they provide security-in-depth for any application using PHP. As a penetration tester, it’s important to be able to tell developers what they’re doing wrong when vulnerabilities are discovered and understanding how a scripting language such as PHP works on a global level.  A huge pet hate of mine is when testers (Nessus, Core Impact or <Insert automated web security scanner> monkeys) report an issue, don’t understand what the issue is, don’t provide a working example and don’t explain the impact specific to the application. Apart from providing a poor service (which the client is probably paying £1000 per day for) this creates the understanding that all penetration testers do is ‘run scans’ and it takes a lot of time and conversations with security managers and developers to reverse!  Rant over, I hope this is useful as both a learning tool and for reference.

An additional source of information regarding PHP and its directives can be found here: .

No comments:

Post a Comment