Is This Authenticated Persistent Cross-Site Scripting (XSS) Vulnerability What Hackers Would be Interested in Woocommerce Products Price Bulk Edit For?
As part of making sure our customers are getting the best information on vulnerabilities in WordPress plugins they may be using we monitor for hackers probing for usage of plugins on our website and then try to figure out what the hackers might be looking to exploit. Today we have had what look to be hackers probing for usage of five plugins. Two of those have recently had vulnerabilities disclosed that involve persistent cross-site scripting (XSS). The other three do not appear to have had vulnerabilities recently disclosed, but have persistent XSS vulnerabilities as well. One of those plugins is Woocommerce Products Price Bulk Edit, which has 20,000+ installs according to wordpress.org and was last updated over two years ago.
In looking over the plugin we found that various functionality that is only intended for WordPress users that are able to edit WooCommerce products are accessible to anyone logged in to WordPress. Seeing as WooCommerce normally creates WordPress accounts for customers that is a big issue. Among the things anyone logged in can do is to delete products (or anything else stored as a WordPress post for that matter), change the price of products, change the title of products (or anything else stored as a WordPress post for that matter), but what seems like it could be of interest to hackers is that a setting can be changed and that can be used to cause authenticated persistent cross-site scripting (XSS).
The plugin resister the function wppbe_update_options() to be accessible to anyone logged in to WordPress:
41 | add_action('wp_ajax_update_options', array( $this, 'wppbe_update_options')); |
That function will update the plugin’s setting without sanitizing or validating the value:
441 442 443 444 445 446 447 448 449 | public function wppbe_update_options() { $products_show_limit = (isset($_POST['show_products_page_limit'])) ? $_POST['show_products_page_limit'] : ''; if($products_show_limit > 0) update_option('wppbe_show_products_page_limit', $products_show_limit); die(); } |
That setting should be an integer, so validating would be a good approach. There also should be a capabilities check and protection against cross-site request forgery (CSRF) before allowing the settings to be changed.
The value is then output by without being escaped in the file /admin/parts/admin-page-content.php, which is run when accessing the plugin’s admin page:
31 | <input type="text" name="show_products_page_limit" id="show_products_page_limit" value="<?php echo get_option('wppbe_show_products_page_limit'); ?>"> |
Combined that is an authenticated persistent cross-site scripting (XSS) vulnerability.
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 leaving a message about that for 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, but considering that they believe that having plugins, which have millions installs, remain in the Plugin Directory despite them knowing they are vulnerable is “appropriate action”, something is very amiss with them (which is even more reason the moderation needs to be cleaned up).
Update: To clear up the confusion where developers claim we hadn’t tried to notify them through the Support Forum (while at the same time moderators are complaining about us doing just that), here is the message we left for this vulnerability:
Proof of Concept
The following proof concept will cause any available cookies to be shown in an alert box on the page /wp-admin/admin.php?page=wppbe, when logged in to WordPress.
Make sure to replace “[path to WordPress]” with the location of WordPress.
<html> <body> <form action="http://[path to WordPress]/wp-admin/admin-ajax.php?action=update_options" method="POST"> <input type="hidden" name="show_products_page_limit" value='1"><script>alert(document.cookie);</script>' /> <input type="submit" value="Submit" /> </form> </body> </html>
Is It Fixed?
If you are reading this post down the road the best way to find out if this vulnerability or other WordPress plugin vulnerabilities in plugins you use have been fixed is to sign up for our service, since what we uniquely do when it comes to that type of data is to test to see if vulnerabilities have really been fixed. Relying on the developer’s information, can lead you astray, as we often find that they believe they have fixed vulnerabilities, but have failed to do that.