Reading Time: 8 minutes

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.

149
150
151
// 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.

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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.

243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
/**
  * 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.

 

 

 

via www.wordfence.com