WordPress 2.8.5 unrestricted File Upload Arbitrary PHP Code Execution

Source: Internet
Author: User
Tags imap wordpress blog

 

========================================================== =====

-Release Date: November 11th, 2009

-Discovered by: dawid golunski

-Severity: moderately high

========================================================== =====

I. Vulnerability

-------------------------

WordPress <= 2.8.5 unrestricted File Upload Arbitrary PHP Code Execution

Ii. Background

-------------------------

WordPress is a state-of-the-art publishing platform with a focus on aesthetics, web standards,

And usability. WordPress is both free and priceless at the same time. More simply, WordPress is

What you use when you want to work with your blogging software, not fight it.

Iii. Description

-------------------------

WordPress allows authorised users to add an attachment to a blog post.

It does not sanitize provided file properly before moving it to an uploads directory.

The part of the code responsible for uploading files looks as follows:

WP-admin/shortdes/file. php:

--- [CUT] ---

Line 217:

Function wp_handle_upload (& $ file, $ overrides = false, $ time = NULL ){

--- [CUT] ---

// All tests are on by default. Most can be turned off by $ override [{test_name}] = false;

$ Test_form = true;

$ Test_size = true;

// If you override this, you must provide $ ext and $ type !!!!

$ Test_type = true;

$ Mimes = false;

--- [CUT] ---

// A properly uploaded file will pass this test. There shocould be no reason to override this one.

If (! @ Is_uploaded_file ($ file ['tmp _ name'])

Return $ upload_error_handler ($ file, _ ('specified file failed upload test .'));

// A correct MIME type will pass this test. Override $ mimes or use the upload_mimes filter.

If ($ test_type ){

$ Wp_filetype = wp_check_filetype ($ file ['name'], $ mimes );

Extract ($ wp_filetype );

If ((! $ Type |! $ Ext )&&! Current_user_can ('unfiltered _ upload '))

Return $ upload_error_handler ($ file,

_ ('File type does not meet security guidelines. Try another .'));

If (! $ Ext)

$ Ext = ltrim (strrchr ($ file ['name'], '.'), '.');

If (! $ Type)

$ Type = $ file ['type'];

} Else {

$ Type = '';

}

// A writable uploads dir will pass this test. Again, there's no point overriding this one.

If (! ($ Uploads = wp_upload_dir ($ time) & false ===$ uploads ['error'])

Return $ upload_error_handler ($ file, $ uploads ['error']);

$ Filename = wp_unique_filename ($ uploads ['path'], $ file ['name'], $ unique_filename_callback );

// Move the file to the uploads dir

$ New_file = $ uploads ['path']. "/$ FILENAME ";

If (false ===@ move_uploaded_file ($ file ['tmp _ name'], $ new_file )){

Return $ upload_error_handler ($ file,

Sprintf (_ ('the uploaded file cocould not be moved to % S. '), $ uploads ['path']);

}

--- [CUT] ---

From the above Code we can see that provided filename gets checked:

$ Wp_filetype = wp_check_filetype ($ file ['name'], $ mimes );

Here is how the wp_check_filetype () function looks like:

WP-shortdes/functions. php:

--- [CUT] ---

Line 2228:

Function wp_check_filetype ($ filename, $ mimes = NULL ){

// Accepted MIME types are set here as PCRE unless provided.

$ Mimes = (is_array ($ mimes ))? $ Mimes: apply_filters ('upload _ mimes ', array (

'Jpg | JPEG | jpe '=> 'image/JPEG ',

'Gif' => 'image/gif ',

'Png '=> 'image/PNG ',

'Bmp '=> 'image/BMP ',

'Tif | tiff '=> 'image/tiff ',

'Ico '=> 'image/X-Icon ',

'Asf | ASX | wax | WMV | wmx '=> 'video/asf ',

'Avi' => 'video/avi ',

--- [CUT, more MIME types] ---

Line 2279:

$ Type = false;

$ Ext = false;

Foreach ($ mimes as $ ext_preg => $ mime_match ){

$ Ext_preg = '! /. ('. $ Ext_preg.') $! I ';

If (preg_match ($ ext_preg, $ filename, $ ext_matches )){

$ Type = $ mime_match;

$ Ext = $ ext_matches [1];

Break;

}

}

Return compact ('text', 'type ');

}

We can see that type of the file gets set to a predefined MIME type that matches supplied

Extension, and that the extension is obtained from a Regexp that matches a mime Ext. String after

The last dot.

If extension is not on the list $ type and $ ext will be set to false and Wordpress will

Produce an error ("file type does not meet security guidelines. Try another ").

Let's look at the other check that is already med on the filename before a file gets uploaded,

That is a call to the following function:

$ Filename = wp_unique_filename ($ uploads ['path'], $ file ['name'], $ unique_filename_callback );

WP-shortdes/functions. php:

Line 2096:

Function wp_unique_filename ($ Dir, $ filename, $ unique_filename_callback = NULL ){

// Sanitize the file name before we begin processing

$ Filename = sanitize_file_name ($ filename );

--- [CUT, code that only matters if uploaded file already exists] ---

Line 2126:

Return $ filename;

}

To have a complete view on file sanitization saved med by WordPress we need to look into

Sanitize_file_name () function:

WP-schemdes/formatting. php:

Line 601:

Function sanitize_file_name ($ filename ){

$ Filename_raw = $ filename;

$ Special_chars = array ("? "," [","] ","/"," // "," = "," <","> ",":",";", ",","'","/"",

"&", "$", "#", "*", "(", ")", "| ","~ ","'","! "," {","} ", CHR (0 ));

$ Special_chars = apply_filters ('sanitize _ file_name_chars', $ special_chars, $ filename_raw );

$ Filename = str_replace ($ special_chars, '', $ filename );

$ Filename = preg_replace ('/[/S-] +/', '-', $ filename );

$ Filename = trim ($ filename ,'.-_');

Return apply_filters ('sanitize _ file_name ', $ filename, $ filename_raw );

}

This function removes special characters shown above, replaces spaces and consecutive dashes

A single dash, TRIMs period, Dash and underscore from beginning and end of the filename.

The sanitization process appears quite extensive however it does not take into account files that

Have multiple extensions.

It is possible to upload a file containing an arbitrary PHP script with an extension of '.php.jpg'

And execute it by requesting the uploaded file directly.

The execution of the PHP Code despite the .php.jpg extension is possible because Apache

Allows for multiple extensions. Here is a quote from Apache docs regarding this matter:

"

Files can have more than one extension, and the order of the extensions is normally irrelevant.

For example, if the file welcome.html. fr

Maps onto content type text/html and language French then

The file welcome.fr.html will map onto exactly the same information. If more than one extension is

Given that maps onto the same type of meta-information, then the one to the right will be used,

Could t for ages and content encodings. For example, if. gif maps to the mime-type image/GIF

And. html maps to the mime-type text/html, then the file welcome.gif.html will be associated

The mime-type text/html.

Care shoshould be taken when a file with multiple extensions gets associated with both a mime-type

And a handler. This will usually result in the request being handled by the module associated

The handler. For example, if the. imap extension is mapped to the handler imap-File

(From mod_imagemap) and the. html extension is mapped to the mime-type text/html, then the file

World.imap.html will be associated with both the IMAP-file handler and text/html mime-type.

When it is processed, the IMAP-file handler will be used, and so it will be treated as

Mod_imagemap Imagemap file.

"

Iv. proof of concept

-------------------------

Browser is enough to replicate this issue. Simply log in to your Wordpress blog as a low privileged

User or admin. Create a New post and use the media file upload feature to upload a file:

Test-image.php.jpg

Containing the following code:

<? PHP

Phpinfo ();

?>

After the upload you shoshould receive a positive response saying:

Test-vuln.php.jpg

Image/JPEG

And it shoshould be possible to request the uploaded file via a link:
Http://link-to-our-wp-unsecured-blog.com/wp-content/uploads/2009/11/test-vuln.php.jpg

Thus executing the PHP code it contains.

In the above code example, a PHP info page will be shown.

V. Business Impact

-------------------------

An attacker that has already obtained login details (for example by stealing user's cookies

An XSS attack) to the blog as one of the existing users cocould exploit this vulnerability to get

Access to the system in the Apache user's context.

From there he cocould use local bugs to further escalate the privileges. Apache account wocould be

Enough in most cases to view the source codes and gain access to the databases.

Some Wordpress users of the 2.8.5 release have reported that some PHP files have been added

Their WordPress directory. It cocould be possible that they have been hit by this bug. Therefore it

Is important to take some countermeasures as soon as possible.

Vi. Systems Affected

-------------------------

Most likely all of the WordPress releases contain this bug. including the current hardened stable

Release 2.8.5 and the beta version.

VII. Solution

-------------------------

Vendor has been informed about the bug. Currently WordPress developers and contributors are in

The process of bug hunting and fixing reported bugs in Beta versions before the new stable release,

So hopefully it shoshould not take long for them to take this problem into account.

You can apply the temporary solutions for this problem which I provide below before an official

Patch is made.

You can create a. htaccess file in the uploads Dir (WordPress/WP-content/uploads)

The following content:

Deny from all

<Files ~ "^/W +/. (GIF | jpe? G | PNG | AVI) $ ">

Order deny, allow

Allow from all

</Files>

Adjust allowed file extensions in the brackets if necessary.

This will prevent Apache from serving files with double extensions inside the uploads directory.

Alternatively you can try to patch the source code yourself by editing

WP-admin/uplodes/file. php file and the wp_handle_upload () function it contains. An example patch

Cocould be to add the following three lines of code at the Line 260:

// Fix unrestricted File Upload Arbitrary PHP code execution bug, return if more than 1 extension provided

If (count (explode ('.', $ file ['name'])> 2 );

Return $ upload_error_handler ($ file, _ ('file type does not meet security guidelines. Try another .'));

VIII. References

-------------------------
Http://www.wordpress.org

Http://httpd.apache.org/docs/2.2/mod/mod_mime.html#multipleext

IX. Credits

-------------------------

This vulnerability has been discovered by dawid golunski

Golunski (AT) ONet (DOT) EU

Greetings go to: robxt, sajanek, xsoti, Bart, Falcon (for the Old time's sake and complexmind

X. revision history

-------------------------

November 11th, 2009: Initial Release

XI. Legal Notices

-------------------------

The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness

Use or otherwise. I accept no responsibility for any damage caused by the use or misuse of this information.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.