• Vulnerability: Code Execution, CSRF, XSS, Information Disclosure
  • Affected Software: WordPress File Upload (WordPress Plugin)
  • Affected Version: 2.7.6 (probably also prior versions)
  • Patched Version: 3.0.0
  • Risk: High
  • Vendor Contacted: 2015-06-30
  • Vendor Fix: 2015-07-02
  • Public Disclosure: 2015-07-02

PHP File Upload


High; Code Execution; no credentials required


The upload of files with the extension php is not allowed. But an attacker can still upload files with the extension php4, php5, or pht which will also be executed, or with extensions htm or html which would lead to XSS, or with extensions php3 or phtml, which would lead to information disclosure, or a file called .htaccess, which would lead to code execution if AllowOverride All is set.


// wfu_processfiles.php:234

                if ( strtolower(substr($only_filename, -4)) != ".php" && strtolower(substr($only_filename, -3)) != ".js" )
                    foreach ($allowed_patterns as $allowed_pattern) {
                        if ( wfu_upload_plugin_wildcard_match( $allowed_pattern, $only_filename) ) {
                            $allowed_file_ok = true;
                            break ;


Do not allow upload of these extensions, or create a whitelist of allowed extensions.



Some requests do not have CSRF protection, for example renaming or deleting files. For more information, see next section.


Use CSRF protection for delete/rename

Insecure File Handling

All of the file/directory handling functions are not restricted to the upload directory, nor to the original extension of the file.


Medium; Any files the webserver user has access to can be downloaded, deleted, or renamed; This leads to Code Execution, DOS, and Information Disclosure (database credentials, etc). Admin credentials or CSRF is required.

List Directories

List directory /etc:


Delete Files

Delete file /secret:


Or without confirmation (for CSRF):

   <form enctype="multipart/form-data" id="myform" method="post" action="http://localhost/wordpress/wp-admin/options-general.php?page=wordpress_file_upload" >
        <input type="hidden" name="action" value="deletefile">
        <input type="hidden" name="dir" value="2f5b5b6e616d655d5d">
        <input type="hidden" name="file" value="2f7365637265745b5b6e616d655d5d">
        <input type="hidden" name="submit" value="Delete">

Download Files

List desired directory and download file.

This works for any file the web user has access to, it is not restricted to the wordpress installation, and it does not conform to the DISALLOW_FILE_EDIT setting, which is intended to disallow read and edit of PHP files.

Rename Files

Rename /var/www/wordpress/wp-content/img.png to /var/www/wordpress/wp-content/index.php

    <form enctype="multipart/form-data" method="post" action="http://localhost/wordpress/wp-admin/options-general.php?page=wordpress_file_upload">
        <input type="hidden" name="action" value="renamefile">
        <input type="hidden" name="dir" value="2f7661722f7777772f776f726470726573732f77702d636f6e74656e745b5b6e616d655d5d">
        <input type="hidden" name="file" value="2f7661722f7777772f776f726470726573732f77702d636f6e74656e742f696d672e706e675b5b6e616d655d5d">       
        <input name="wfu_newname" type="hidden" value="index.php" />
        <input type="submit" class="button-primary" name="submit" value="Rename">


With admin credentials:

  • download wp-config.php -> access to database
  • download any file on server the webuser has access to -> possibly escalate privileges
  • see without credentials Without credentials (no CSRF protection):

  • delete important files (via CSRF) -> DOS

  • upload valid image file, use rename (via CSRF) to change it to .php -> code execution


  • The rename functionality should restrict renames to the same directory and the same extension, inside the upload directory
  • The delete/list/download functionalities should restrict these actions to the upload directory
  • (the upload directory setting should be restricted as well, to avoid information disclosure and DOS by someone gaining admin credentials and then changing that directory)

Multiple Reflected XSS


Medium; Arbitrary JavaScript execution; combined with above vulnerabilities, this can lead to code execution




The encoded string represents






The encoded string represents

/index.php<img src="no" onerror="alert(1)"> [[name]]

(an attacker can’t use a slash as it marks a directory)


Encode user input before echoing it.


  • 2015-06-30 Initial Report
  • 2015-06-30 Vendor Confirmation
  • 2015-07-01 Vendor Asking For Clarification
  • 2015-07-01 Clarified + Reported Further Issues
  • 2015-07-01 Vendor Send Fix for Confirmation
  • 2015-07-02 Confirmed Fix
  • 2015-07-02 Vendor Released Fix
  • 2015-07-02 Disclosure