There are SQLi and unauthenticated stored XSS vulnerabilities in Discount Rules for the WooCommerce WordPress plugin.
The Discount Rules for the WooCommerce plugin (versions 2.0.2 and below) suffer from multiple vulnerabilities such as SQL injection, authorization issues, and unauthenticated stored cross-site scripting.
In this scenario, the unauthenticated stored cross-site scripting issue could potentially lead to remote code execution.
The plugin is described as a plugin that helps you to create any type of bulk discounts, dynamic pricing, advanced discounts, percentage discounts, product-based discounts, tiered discounts for your products. It has 30.000+ active installations as of August 7th, 2020.
The described issues were fixed in version 2.1.0 after a rapid response by the developer team of the plugin in question.
Update August 24, 2020
Based on our logs, there was another influx of attacks blocked on August 23rd. The IP address 95.181.152.136 attempted to inject the scripts stock[dot]developerstatss[dot]ga/stock.js?v=1 and stock[dot]developerstatss[dot]ga/stock.js?v=2 into the template hooks woocommerce_before_main_content, woocommerce_after_main_content and footer. This script seems to redirect the visitor to their own malicious site.
Update August 21, 2020
We have seen an influx of attacks against this vulnerability. Primarily from the IP address 45.140.167.17 which attempts to inject the script poponclick[dot]info/click.js into the woocommerce_before_main_content template hook. This seems to indicate that they are attempting to target WooCommerce based sites with this outdated plugin version installed.
We will continue to monitor this threat and will update this post with more information when available.
The vulnerability in Discount Rules for WooCommerce
The issues in this plugin are caused due to a lack of authorization and nonce token check. The plugin registers several AJAX actions of which one, wp_ajax_wdr_ajax, handles a bulk of different AJAX actions which are supposedly only be accessed by administrators.
Unfortunately this AJAX action is also registered as wp_ajax_nopriv_wdr_ajax. Even if wp_ajax_nopriv_wdr_ajax was not registered, authenticated users could still exploit this since wp_ajax_wdr_ajax does not perform any type of authorization or CSRF check.
A snippet of what the function wdr_ajax_requests looks like (which is bound to both AJAX actions) can be found below.
public function wdr_ajax_requests()
{
$result = null;
$method = $this->input->post('method', '');
$method_name = 'wdr_ajax_' . $method;
if (method_exists($this, $method_name)) {
$result = $this->$method_name();
}
wp_send_json_success($result);
}
It grabs the method that it needs to execute from the method POST parameter and then executes it as long as it’s part of the current class scope. Some of the methods in the class are of no interest, but there are a few that could lead to serious vulnerabilities.
These actions can be executed by any unauthenticated user. There is no authentication, authorization, or CSRF check. Some of the methods of interest can be found below.
- wdr_ajax_users_list
- Retrieve list (userid and username only) of all users.
- wdr_ajax_cart_coupon
- Retrieve the list of all coupon codes.
- wdr_ajax_save_configuration
- Update any of the configuration settings (of the plugin only), allowing you to cause a great financial loss if a shop notices too late.
- Since the values of some of the configuration settings are displayed to the user, unauthenticated stored XSS is possible at both frontend and backend in values such as on_sale_badge_html, applied_rule_message, and awdr_banner_editor which in turn could trigger a remote code execution exploit since we can execute any type of code on the admin screen.
- The combination of overwriting the values awdr_banner_editor and display_banner_text allows any unauthenticated user to inject XSS into any display location they desire, such as the header, footer or any admin page.
- wdr_ajax_save_rule
- Save a discount rule.
- wdr_ajax_delete_rule
- Delete a discount rule.
- wdr_ajax_duplicate_rule
- Duplicate a discount rule.
- This method is also vulnerable to SQL injection since the rowid POST parameter is directly used in a SQL query.
- wdr_ajax_bulk_action
- Bulk enable, disable, or delete discount rules.
The patch in Discount Rules for WooCommerce
The patch for version 2.1.0 can be found here which shows that they added an authorization and CSRF check to the admin methods.
The image below shows that the AJAX action handler can now only be executed by authorized users. Or if the action is a public frontend AJAX action. The individual AJAX admin actions also determine if a valid CSRF token is present.
Timeline
07-08-2020 – We discovered the vulnerability in Discount Rules for WooCommerce and released a vPatch to all Patchstack paid version customers.
07-08-2020 – We reported the issue to the developer of the plugin.
07-08-2020 – The developer replied and started working on a fix.
12-08-2020 – The developer asked us to review the fixed version, which we approved.
13-08-2020 – Version 2.1.0 was released which contains the proper fixes.
20-08-2020 – Published the article.
Websites with Patchstack paid version are protected from the issue and have received a vPatch.