Filesystem Security with PHP

PHP has the ability to directly access the files system and even execute shell commands. While this affords developers great power, it can be very dangerous when tainted data ends up in a command line. Again, proper filtering and escaping can mitigate these risks.

Remote Code Injection
When including files with include and require, pay careful attention when using possibly tainted data to create a dynamic include based on client input, because a mistake could easily allow would-be hackers to execute a remote code injection attack. A remote code injection attack occurs when an attacker is able to cause your application to execute PHP code of their choosing. This can have devastating consequences for both your application and system.

For example, many applications make use of query string variables to structure the application into sections, such as: One such application may use an include statement to include a script to display the “news” section:

include "{$_GET['section']}/";

When using the proper URL to access this section, the script will include the file located at news/ However, consider what might happen if an attacker modified the query string to include harmful code located on a remote site? The following URL illustrates how an attacker can do this:

Now, the tainted section value is injected into the include statement, effectively rendering it as such:

include "";

The application will include, located on the remote server, which treats / as part of the query string (thus effectively neutralizing its effect within your script). Any PHP code contained in is executed and run, causing whatever harm the attacker intended.

While this attack is very powerful, effectively granting the attacker all the same privileges enjoyed by the Web server, it is easy to protect against it by filtering all input and never using tainted data in an include or require statement. In this example, filtering might be as simple as specifying a certain set of expected values for section:

$clean = array();
$sections = array('home', 'news', 'photos', 'blog');
if(in_array($_GET['section'], $sections)){
   $clean['section'] = $_GET['section'];
   $clean['section'] = 'home';

include "{clean[’section’]}/";
The allow_url_fopen directive in PHP provides the feature by which PHP can access URLs,
treating themlike regular files—thus making an attack such as the one described here possible.
By default, allow_url_fopen is set to On; however, it is possible to disable it in php.ini,
setting it to Off, which will prevent your applications from including or opening remote URLs
as files.

Command Injection
As allowing client input to dynamically include files is dangerous, so is allowing the client to affect the use of system command execution without strict controls. While PHP provides great power with the exec(), system() and passthru() functions, aswell as the ‘ (backtick) operator, these must not be used lightly, and it is important to take great care to ensure that attackers cannot inject and execute arbitrary system commands.

Again, proper filtering and escaping will mitigate the risk—a whitelist filtering approach that limits the number of commands that users may execute works quite well here. Also, PHP provides  escapeshellcmd() and escapeshellarg() as a means to properly escape shell output.

When possible, avoid the use of shell commands. If they are necessary, avoid the use of client input to construct dynamic shell commands.

Next Topic | Previous Topic

Post to Twitter Post to Digg Post to Facebook Post to Google Buzz Send Gmail

Leave a Comment

Your email address will not be published. Required fields are marked *