700,000 WordPress Users Affected by Zero-Day Vulnerability in File Manager Plugin

This morning, on September 1, 2020, the Wordfence Threat Intelligence team was alerted to the presence of a vulnerability being actively exploited in File Manager, a WordPress plugin with over 700,000 active installations. This vulnerability allowed unauthenticated users to execute commands and upload malicious files on a target site.

A patch was released this morning on September 1, 2020. We are seeing this vulnerability being actively exploited in the wild, therefore, we urge users to update to the latest version, 6.9, immediately since it contains a patch for this vulnerability and will keep you protected.

Wordfence Premium users as well as those still using the Free version are protected against this attack campaign by the Wordfence firewall’s built-in file upload protection, though the Wordfence firewall needs to be optimized in order to protect your site from this vulnerability.

While analyzing the vulnerability, we discovered that it was possible to bypass the built-in file upload protection so we deployed an additional firewall rule for maximum coverage. Wordfence Premium customers received this new firewall rule today, September 1, 2020, at 2:56PM UTC. Free Wordfence users will receive the rule after thirty days on October 1, 2020.

Description: Remote Code Execution
Affected Plugin: File Manager
Plugin Slug: wp-file-manager
Affected Versions: 6.0-6.8
CVSS Score: 10.00 (Critical)
CVSS Vector: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Patched Versions: 6.9

File Manager is a plugin designed to help WordPress administrators manage files on their sites. The plugin contains an additional library, elFinder, which is an open-source file manager designed to create a simple file management interface and provides the core functionality behind the file manager. The File Manager plugin used this library in a way that introduced a vulnerability.

The core of the issue began with the File Manager plugin renaming the extension on the elFinder library’s connector.minimal.php.dist file to .php so it could be executed directly, even though the connector file was not used by the File Manager itself. Such libraries often include example files that are not intended to be used “as-is” without adding access controls, and this file had no direct access restrictions, meaning the file could be accessed by anyone. This file could be used to initiate an elFinder command and was hooked to the elFinderConnector.class.php file.

// run elFinder
$connector = new elFinderConnector(new elFinder($opts));
$connector->run();

Any parameters sent in a request to connector.minimal.php would be processed by the run() function in the elFinderConnector.class.php file, including the command that was supplied in the cmd parameter.

   public function run()
    {
        $isPost = $this->reqMethod === 'POST';
        $src = $isPost ? array_merge($_GET, $_POST) : $_GET;
        $maxInputVars = (!$src || isset($src['targets'])) ? ini_get('max_input_vars') : null;
        if ((!$src || $maxInputVars) && $rawPostData = file_get_contents('php://input')) {
            // for max_input_vars and supports IE XDomainRequest()
            $parts = explode('&', $rawPostData);
            if (!$src || $maxInputVars < count($parts)) {
                $src = array();
                foreach ($parts as $part) {
                    list($key, $value) = array_pad(explode('=', $part), 2, '');
                    $key = rawurldecode($key);
                    if (preg_match('/^(.+?)\[([^\[\]]*)\]$/', $key, $m)) {
                        $key = $m[1];
                        $idx = $m[2];
                        if (!isset($src[$key])) {
                            $src[$key] = array();
                        }
                        if ($idx) {
                            $src[$key][$idx] = rawurldecode($value);
                        } else {
                            $src[$key][] = rawurldecode($value);
                        }
                    } else {
                        $src[$key] = rawurldecode($value);
                    }
                }
                $_POST = $this->input_filter($src);
                $_REQUEST = $this->input_filter(array_merge_recursive($src, $_REQUEST));
            }
        }

        if (isset($src['targets']) && $this->elFinder->maxTargets && count($src['targets']) > $this->elFinder->maxTargets) {
            $this->output(array('error' => $this->elFinder->error(elFinder::ERROR_MAX_TARGTES)));
        }

        $cmd = isset($src['cmd']) ? $src['cmd'] : '';
        $args = array();

The list of commands available in elFinder are as follows.

   /**
     * Commands and required arguments list
     *
     * @var array
     **/
    protected $commands = array(
        'abort' => array('id' => true),
        'archive' => array('targets' => true, 'type' => true, 'mimes' => false, 'name' => false),
        'callback' => array('node' => true, 'json' => false, 'bind' => false, 'done' => false),
        'chmod' => array('targets' => true, 'mode' => true),
        'dim' => array('target' => true, 'substitute' => false),
        'duplicate' => array('targets' => true, 'suffix' => false),
        'editor' => array('name' => true, 'method' => true, 'args' => false),
        'extract' => array('target' => true, 'mimes' => false, 'makedir' => false),
        'file' => array('target' => true, 'download' => false, 'cpath' => false, 'onetime' => false),
        'get' => array('target' => true, 'conv' => false),
        'info' => array('targets' => true, 'compare' => false),
        'ls' => array('target' => true, 'mimes' => false, 'intersect' => false),
        'mkdir' => array('target' => true, 'name' => false, 'dirs' => false),
        'mkfile' => array('target' => true, 'name' => true, 'mimes' => false),
        'netmount' => array('protocol' => true, 'host' => true, 'path' => false, 'port' => false, 'user' => false, 'pass' => false, 'alias' => false, 'options' => false),
        'open' => array('target' => false, 'tree' => false, 'init' => false, 'mimes' => false, 'compare' => false),
        'parents' => array('target' => true, 'until' => false),
        'paste' => array('dst' => true, 'targets' => true, 'cut' => false, 'mimes' => false, 'renames' => false, 'hashes' => false, 'suffix' => false),
        'put' => array('target' => true, 'content' => '', 'mimes' => false, 'encoding' => false),
        'rename' => array('target' => true, 'name' => true, 'mimes' => false, 'targets' => false, 'q' => false),
        'resize' => array('target' => true, 'width' => false, 'height' => false, 'mode' => false, 'x' => false, 'y' => false, 'degree' => false, 'quality' => false, 'bg' => false),
        'rm' => array('targets' => true),
        'search' => array('q' => true, 'mimes' => false, 'target' => false, 'type' => false),
        'size' => array('targets' => true),
        'subdirs' => array('targets' => true),
        'tmb' => array('targets' => true),
        'tree' => array('target' => true),
        'upload' => array('target' => true, 'FILES' => true, 'mimes' => false, 'html' => false, 'upload' => false, 'name' => false, 'upload_path' => false, 'chunk' => false, 'cid' => false, 'node' => false, 'renames' => false, 'hashes' => false, 'suffix' => false, 'mtime' => false, 'overwrite' => false, 'contentSaveId' => false),
        'url' => array('target' => true, 'options' => false),
        'zipdl' => array('targets' => true, 'download' => false)
    );

The good news is that elFinder has built-in protection against directory traversal, so an attacker would be unable to use any of these commands on any files outside of the plugins/wp-file-manager/lib/files/ directory.

The attacks we are seeing in the wild are using the upload command to upload PHP files containing webshells hidden in an image to the wp-content/plugins/wp-file-manager/lib/files/ directory.

Fortunately, both Wordfence Premium and free users have been protected against the campaign targeting this vulnerability. However, for optimal protection we created an additional firewall rule.

Why We Created An Additional Firewall Rule

While our firewall’s built-in protection prevented direct file upload, we determined that it was possible to send a specially crafted request that would create an empty PHP file by using the mkfile command in the cmd parameter. An attacker could then send a separate request to save malicious code to that file by sending a request with the cmd parameter set to put. Additionally, other bypasses may be possible, so we created a firewall rule to completely block any and all access to the connector.minimal.php file.

The File Manager plugin patched the issue by removing the lib/php/connector.minimal.php file from the plugin altogether, and manually removing this file should also prevent attackers from exploiting this vulnerability without impacting normal functionality. This bypass has not been targeted in the wild.

A Small Note From The Team at Wordfence

When using utility plugins like this file manager plugin, we recommend taking the utmost precaution. Plugins like this one contain several features that if exposed within the admin area of your WordPress installation, could cause serious problems.

A file manager plugin like this would make it possible for an attacker to manipulate or upload any files of their choosing directly from the WordPress dashboard, potentially allowing them to escalate privileges once in the site’s admin area. For example, an attacker could gain access to the admin area of the site using a compromised password, then access this plugin and upload a webshell to do further enumeration of the server and potentially escalate their attack using another exploit.

For this reason, we recommend uninstalling utility plugins, like file management plugins, when they are not in use, so that they do not create an easy intrusion vector for attackers to escalate their privileges.

Indicators of Compromise

The Wordfence firewall has blocked over 450,000 exploit attempts targeting this vulnerability over the past several days. We are seeing attackers attempting to inject random files, all of which appear to begin with the word “hard” or “x.” From our firewall attack data, it appears that attackers may be probing for the vulnerability with empty files and if successful, may attempt to inject a malicious file.

Here is a list of some of the files we are seeing uploaded:

  • hardfork.php
  • hardfind.php
  • x.php

Please look for these files in the /wp-content/plugins/wp-file-manager/lib/files directory of your site.

The top 6 attacking IP addresses that we are seeing are as follows.

  • 185.222.57.183
  • 185.81.157.132
  • 185.81.157.112
  • 185.222.57.93
  • 185.81.157.177
  • 185.81.157.133

Please look for these offending IP Addresses in your site’s log files.

Response Timeline

September 1, 2020 7:00AM UTC – Gonzalo Cruz from Arsys reaches out to us, letting us know that an offending IP address 185.81.157.0 was attempting to upload PHP files to their sites by sending POST requests to wp-file-manager/lib/php/connector.minimal.php
September 1, 2020 11:52AM UTC – Cruz was able to reproduce the vulnerability and provided us with a working proof of concept.
September 1, 2020 12:00PM UTC – Wordfence team starts the day.
September 1, 2020 12:28PM UTC – Colette Chamberland, Wordfence’s Director of Information Security, responds to Cruz acknowledging his report and notifies the Wordfence Threat Intelligence team of the report.
September 1, 2020 12:33 PM UTC – File Manager releases a patch.
September 1, 2020 12:48PM UTC – The Wordfence Threat intelligence team begins looking into the issue.
September 1, 2020 12:58PM UTC – The Wordfence Threat Intelligence team verifies the issue. We begin testing the vulnerability using the proof of concept, check blocked hits from the Wordfence Firewall, and analyze the code for any firewall bypasses.
September 1, 2020 2:24PM UTC – The Wordfence Threat Intelligence team discovers a bypass.
September 1, 2020 2:42PM UTC – A firewall rule is created for the bypass.
September 1, 2020 2:56PM UTC – The firewall rule is deployed for premium customers.
October 1, 2020 – Wordfence free users receive additional rule.

Conclusion

In today’s post, we detailed a zero-day vulnerability being actively exploited in the File Manager plugin that allows unauthenticated attackers to execute arbitrary code on a WordPress site. This vulnerability was patched this morning and we strongly recommend updating to the latest version of the File Manager plugin, currently version 6.9, right now.

Both Wordfence Premium users and sites still running the free version of Wordfence have been protected against attacks targeting this vulnerability due to the Wordfence firewall’s built-in File Upload protection. Wordfence Premium users also received an additional firewall rule protecting against any potential bypasses today, September 1, 2020. Sites still using the free version of Wordfence will receive this rule in 30 days on October 1, 2020.

If you know a friend or colleague who is using this plugin on their site, please forward this advisory to them to help keep their sites protected.

Special thanks to Ramuel Gall for his research contributions in analyzing the scope and impact of the vulnerability along with testing the firewall rule and contributing to this blog post. Also, a special thanks to Gonzalo Cruz from Arsys for reporting this vulnerability to us.

Did you enjoy this post? Share it!

Comments

16 Comments
  • We've noticed yesterday injected random named files in a wp file manager 6.7 installation in the plugins folder like /libs/files/jhsdfjsfd.php

    • You gotta get those files cleared out asap. And make sure new ones don't reappear.

    • Hi Rene,

      I'm sorry to hear your site was affected. Please follow our site cleaning guide to ensure you have removed the entire infection, update the plugin immediately to prevent any re-infections, and ensure you have the Wordfence firewall running and optimized. Alternatively, you can use our site cleaning service where our team of experts will handle to site cleaning process for you.

    • I updated to the latest version and my issues are now solved.

  • What if i have a .htpasswd on my site?

    • Hi Rob,

      If you have .htpasswd protecting your entire site (including front-end and back-end) you shouldn't have anything to worry about. If the .htpasswd file is only protecting the /wp-admin area, then your site would still be considered vulnerable to this exploit. Regardless, I would recommend updating to the latest version available as soon as possible.

  • Attacks for us started on the 25th for another products with ElFinder. This attacker you listed appeared around the 29th.
    20.37.246.247 (Looking for another plugin with ElFinder, not wp file manager )
    Other IPs you missed:
    107.172.100.204
    185.244.172.39
    195.206.107.28
    162.144.212.16

    • Thank you for adding additional information! For brevity we only included the top 6 offending IPs, there were several more on the list omitted from this post.

  • Just noticed I got this weird activity, thanks to cleantalk. However the reports are from 2 IPs (Taiwan) ;
    wp-content/plugins/wp-file-manager/lib/php/connector.minimal.php (IP 2002:b951:9d70::b951:9d70)
    wp-content/plugins/wp-file-manager/lib/php/connector.minimal.php (IP 2002:b951:9def::b951:9def).

    I don't remember I ever installed WP File Manager on my website, since I cannot find the plugin installed (I checked on WP dashboard and Cpanel folder).

    • Hi Ritz,

      Attackers will probe any and all sites they can access to see if the vulnerability exists. It's very possible you do not have the WP File Manager plugin installed on your site, but attackers are checking if you do. You can check for this plugin in the plugins area of your WordPress site, and if it is not there it is then it is safe to assume you do not have the plugin installed on your site and you have nothing to worry about.

  • I got this attack by uploading wp-stream.php from this ip 95.181.152.136

  • I have been effected by this problem if I follow the recomendations above will this bring back my website as it was prior to the attack or do I ave to do something else.

    I am usinf a free version of Wordfence if I upgrade to Premuim will this solve the problem and retore my web site ???

    • Hi Thomas,

      I am sorry to hear you have been affected by this vulnerability! Please follow this guide to clean your site. Alternatively, you can hire our site security services team to perform a clean-up and investigation, this service includes a free year of Wordfence Premium.

  • I contacted their support as soon as I heard this and they scheduled a call with me to update my plugin and scanned my entire website.
    I would suggest you update your plugin immediately to the latest version and still if you are facing some issue contact their customer support.

  • Hi, Hope you are doing well. My website also affected by this vulnerability. we clean the code now. Please recommend now how to scan the site for confirmation.

    • Hi Uzair,

      Please follow this guide to ensure clean your site and make sure you have scanned your site with the Wordfence scanner once completed to ensure there is no more malware present on your installation.