Saturday, June 18, 2011

File path injection in PHP ≤ 5.3.6 file upload (CVE 2011-2202)

Since the thing went public before new PHP version has been released, I present full details of the latest PHP vulnerability I reported - together with some sweet demo exploit. The issue was found with fuzzing being part of my recent file upload research. And I still have some more to show in the future :)

My thanks go to Paweł Goleń who helped analyze the vulnerability.

The PHP Part

The whole issue is tracked as PHP bug #54939, but the website is now down. The exemplary exploit is at pastebin. The nature of the bug is simple. PHP claims to remove the path component from HTTP file upload forms (transferred as MIME multipart/form-data requests), leaving only the file name given by the user agent. This is both for security, and to fix MSIE incompatibility (IE used to send full path like this: c:\WINDOWS\WHATEVER\My_file.txt).

However, in 2008 PHP developers made a off-by-one error, and, as a result, if a name starts with \ or / and has no other (back)slashes, it's left as-is. So, this allows for:
  • /vmlinuz
  • /autorun.inf (/ will map to C:\ in WINDOWS - the drive where your PHP is run from)
  • /boot.ini
and other interesting file "names" to pass through.

The application part

Of course, what this means is simply that $_FILES[$input_field_name]['name'] will contain unsanitized file path - and that's not enough to complete an exploit. PHP script would need to use that filename as a destination for file writing. Unfortunately, at least a few applications do. I've found some pretty interesting examples. Among them is this AjaxFileUpload plugin. There are more applications with the same approach - just go on looking! AjaxFileUpload simply passes the given file "name" to move_uploaded_file(), which would try to create/overwrite a file in a root directory...

The set up part

And that will most likely fail, because of insufficient permissions. Who on Earth would allow PHP to write to root? Well, default Apache installation on Windows systems is run as a SYSTEM user (a.k.a root). Also, for some shared hostings PHP is run in a chroot-ed environment, and / is the document root of a website (which allows for an easy site defacement). It's tricky, I agree, that's why this bug is v. difficult to exploit in the wild (luckily).

But it's possible!

Today's Heroes:
  • WAMP server, newest version (PHP 5.3.5), default install
  • PHP <= 5.3.6, (5.3.5 in the demo)
  • Windows XP
  • AjaxFileUpload - A jQuery plugin that simulates asynchronous file uploads.
In the exploit I simply show that (thanks to vulnerable set up) I can overwrite c:\boot.ini and make the system unbootable. There are more advanced scenarios that could be done (essentially I can supply a boot record file to use on next boot), but it's not my area of expertise. To upload a file, the HTML5 arbitrary file upload technique was used.

So, patch your PHPs and bye!


justin perras said...

Cool story bro. I'm glad you created a perfect environment in which to execute this seemingly irrelevant and impractical exploit. If you need attention this badly, maybe you should do more things naked. ;]

kkotowicz said...

Nowhere did I claim this has any real-world value, which I also mention in a post. It's rather a funny example for me of what could be done with just off-by-one. 

Lava said...

No doubt this is a rare scenario but as any pentester would know, such quirks can come in handy when you don't have a direct point of entry and have to resort to exploit-chaining.

Gynvael Coldwind said...


Pawel Golen said...

Binary planting  was considered during our brainstorming on the subject "how to show that this vulnerability may be really dangerous".  Overwriting ntldr or also was considered, but it should be overwritten with something usefull to gain something more then DoS. I've just realized that for this PoC it might be useful to use sources from ReactOS project althought I don't know if ReactOS also uses ntdetect and ntldr.

From the other hand this vulnerability may be useful in real world scenarios. On some hosting platforms root directory is set to root directory of website. In some cases bad programming practices, lack of documentation on the subject what $_FILE[]['name'] really is (or might be) and this bug found by Krzysztof may result in website defacement.

kkotowicz said...


Apart form scenarios mentioned by you and Paweł, we thought of putting autorun.inf or a malicious .inf file ( ) on a root drive. But Windows exploitation is not my pair of shoes, so I'll just leave it at this simple boot DoS.

kkotowicz said...

Considering the 'hosting with chroot' situation - it would be very convenient to be able to upload /crossdomain.xml, wouldn't it? ;) That is universal (i.e. works for all sites), it's less invasive then defacement, so it might not be spotted right away.

Dana Lapid said...

I'm using a php code generator right now in order to finish a website I promised to built for a customer,  what did the bug effected exactly?!