Cross-Site Request Forgery Vulnerability Patched in Ecwid Ecommerce Shopping Cart Plugin

On June 24, 2022, the Wordfence Threat Intelligence team initiated the responsible disclosure process for a Cross-Site Request Forgery vulnerability we discovered in Ecwid Ecommerce Shopping Cart, a WordPress plugin installed on over 30,000 sites. This vulnerability made it possible for attackers to modify some of the plugin’s more advanced settings via a forged request.

We attempted to reach out to the developer on June, 24, 2022 via their ticketing system. After several plugin updates did not address the issue and we received no response from the developer, we disclosed this vulnerability to the plugins team on July 11, 2022. The vulnerabilities were fixed a few days later in version 6.10.24 on July 13, 2022.

Due to the nature of Cross-Site Request Forgery vulnerabilities, which involve tricking administrators into performing actions they are allowed to perform, it is not possible to provide adequate protection for these vulnerabilities without blocking legitimate requests. As such, we highly recommend updating to version 6.10.24 or higher of Ecwid Ecommerce Shopping Cart to ensure that your site is protected against any exploits targeting this vulnerability.

Description: Cross-Site Request Forgery to Settings/Options Update
Affected Plugin: Ecwid Ecommerce Shopping Cart
Plugin Slug: ecwid-shopping-cart
Affected Versions: <= 6.10.23
CVE ID: CVE-2022-2432
CVSS Score: 8.8 (High)
CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Researcher/s: Marco Wotschka
Fully Patched Version: 6.10.24

Ecwid Ecommerce Shopping Cart is a plugin offered by Lightspeed that allows site owners to set up an eCommerce store on a WordPress website and then sync it across various services such as Amazon and social media. It also offers ad integration and access to marketing tools. As part of the plugin’s functionality, there were some more advanced settings that could be managed. Unfortunately, this was implemented insecurely making it possible for attackers to update these settings via a forged request.

More specifically, the plugin provides the following admin_post action hooked to the ‘ecwid_update_plugin_params‘ function for that purpose:

add_action('admin_post_' . ecwid_get_update_params_action(), 'ecwid_update_plugin_params');

An initial check in the ‘ecwid_update_plugin_params‘ function ensures that the current user is allowed to manage site options, which is a capability that belongs to administrators. However, the nonce check performed shortly after is only executed if a nonce is set due to how the function uses && to combine the checks to validate that a nonce is present in the request and to verify that the nonce is valid. This means that if the wp-nonce parameter is not supplied in the request, the verification step is skipped. This makes the functionality susceptible to Cross-Site Request Forgery attacks in vulnerable versions.

add_action('admin_post_' . ecwid_get_update_params_action(), 'ecwid_update_plugin_params');
function ecwid_update_plugin_params()
{
   if ( !current_user_can('manage_options') ) {
      wp_die( __( 'Sorry, you are not allowed to access this page.' ) );
   }
   
   if ( isset($_POST['wp-nonce']) && !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['wp-nonce'])), ecwid_get_update_params_action()) ) {
      wp_die( __( 'Sorry, you are not allowed to access this page.' ) );
   }

   $options = ecwid_get_update_params_options();
   
   $options4update = array();
   
   foreach ( $options as $key => $option ) {
      if( !isset($_POST['option'][$key]) ) {
         continue;
      }

      if ( isset($option['type']) && $option['type'] == 'html' ) {
         $options4update[$key] = sanitize_textarea_field(wp_unslash( $_POST['option'][$key] ));
      } else {
         $options4update[$key] = sanitize_text_field(wp_unslash( $_POST['option'][$key] ));
      }

      if( $key == 'ecwid_store_id' ) {
         $options4update[$key] = intval($options4update[$key]);
      }
   }
   
   foreach ($options4update as $name => $value) {
      update_option($name, $value);  
   }
   
   wp_safe_redirect('admin.php?page=ec-params');
   exit();
}

This makes it possible for an attacker to change the ecwid_store_id, which uniquely identifies the store and is needed for support requests as well as for embedding the store on other sites. Another site option that could be modified is the site’s ecwid_store_page_id, which is the storefront page in the WordPress installation. Both of these settings may result in a loss of availability of the storefront if changed to an invalid store ID. There are several other settings that could be affected in addition to those two. The plugin does not provide a direct link to the settings page in any of its menus and a warning on the page suggests that modifying these settings may significantly affect the plugin functionality.

The Importance of Properly Implementing Nonces

Nonces are a critical component used to prevent Cross-Site Request Forgery vulnerabilities. As such, it’s important to ensure they are properly implemented throughout plugin and theme code to prevent unauthorized execution of that code. Fortunately, WordPress provides several mechanisms to create and validate proper nonces.

Nonce Creation

The first step to proper nonce implementation is nonce creation.

One option to properly implement nonce creation involves the wp_nonce_url() function. This function expects a target URL as well as an action and an optional nonce name. The nonce will be added to a URL and can be verified by a nonce validation function that is executed in the same or subsequent function. This makes it possible for developers to provide links to perform actions such as deletion of posts with a proper nonce that allows the code to verify that the action was initiated from within the site as opposed to a click on a link elsewhere, such as in an email.

An additional option is adding a nonce to a form to secure any submissions originating from that form. The function wp_nonce_field() is frequently used in these cases and expects an action string. This will add a hidden input field to the form. Upon form submission, the created nonce can be checked and verified.

Finally, a nonce can also be generated using wp_create_nonce(), which accepts an action string argument and returns just a nonce. This can be implemented in a variety of different ways and allows more flexibility as a developer to implement nonce validation. We frequently see this function contained in HTML on setting pages that is later used to validate the origin of the request when saving those settings.

Remember that nonces are specific to individual users and sessions and are invalidated after 24 hours, or on logout.

Nonce Validation

The second step to proper nonce implementation involves nonce verification. A plugin can implement an appropriate nonce on a form or settings update, but without proper validation of that nonce, there won’t be adequate protection.

The first option to properly validate a nonce involves the use of the check_admin_referer() function. This function accepts the protected action as well as the name of the nonce as an argument and checks the nonce as well as the referer, thus helping to ensure that the nonce provided is correct and that the request was initiated from an admin page.

When implementing an AJAX action, the check_ajax_referer() function can be used. This will verify the nonce but will not check the referer like the check_admin_referer() function does although it will validate that the request is an AJAX request.

A final option for validating a nonce is the more general wp_verify_nonce() function. With this function, an action and nonce name will need to be supplied, and it will verify that the proper nonce was set. This provides the most flexible implementation of nonce validation for developers.

In the case of today’s disclosure, the nonce was created on the settings form itself with wp_create_nonce():

	<input type="hidden" name="nonce" value="<?php echo wp_create_nonce( ecwid_get_update_params_action() ); ?>" />

However, the nonce verification was not performed correctly:

	if ( isset($_POST['wp-nonce']) && !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['wp-nonce'])), ecwid_get_update_params_action()) ) {
		wp_die( __( 'Sorry, you are not allowed to access this page.' ) );
	}

As you can see, this statement will call wp_verify_nonce() but only if the nonce is set due to the if (isset($_POST['wp-nonce']) check and the use of && in combination with the wp_verify_nonce() function. Therefore, if the nonce is omitted, this check will not take place.

This serves as an important reminder to not only properly implement nonces and validation checks but also to ensure that the check fails when the nonce value is empty or otherwise not present.

As a final important note: never rely on nonce checks alone. Developers should always remember to include a capability check using a function like current_user_can() in order to ensure the user initiating the action is indeed allowed to perform it. Nonces should never be used for authentication, authorization or any form of access control as they are simply intended to verify the origin of the request, and do not perform any authorization.

Timeline

  • June 24, 2022 – Initial outreach to the plugin developer.
  • July 11, 2022 – We escalate the issue to the WordPress.org plugins team and send them the full disclosure details.
  • July 13, 2022 – The vulnerability is patched in version 6.10.24.

Conclusion

In today’s post, we covered a vulnerability in the Ecwid Ecommerce Shopping Cart plugin that could be used to trick site administrators into updating plugin settings due to improper nonce verification. The vulnerability was patched by ensuring that a proper nonce was set and by verifying it.

Please remember that due to the nature of Cross-Site Request Forgery vulnerabilities, it is not possible to provide adequate protection via the Wordfence firewall without blocking legitimate requests. As such, we highly recommend updating to version 6.10.24 or higher of Ecwid Ecommerce Shopping Cart to ensure that your site is protected against any exploits targeting this vulnerability.

If you believe your site has been compromised as a result of this vulnerability or any other vulnerability, we offer Incident Response services via Wordfence Care. If you need your site cleaned immediately, Wordfence Response offers the same service with 24/7/365 availability and a 1-hour response time. Both of these products include hands-on support in case you need further assistance.

If you have any friends or colleagues who are using this plugin, please share this announcement with them and encourage them to update to the latest patched version of Ecwid Ecommerce Shopping Cart as soon as possible.

Did you enjoy this post? Share it!

Comments

2 Comments
  • Hi, Marko!

    This is Ilnur from Ecwid by Lightspeed team.

    Thanks for your report! Appreciate it!

    Unfortunately, on June 24 we did not receive your letter on this issue. We would fix it right away. Anyway, thank you.

    If you have any reports to submit, please contact us at whitehat AT ecwid.com. More about our bug bounty program here https://github.com/Ecwid/security-bug-bounty.

    • Thanks for sharing this information! We were not aware you had a disclosure program, and did not find those details when we made our initial outreach. We will be sure to use that address if we ever discover any issues in the future. Hopefully this information can also help any other security researchers that may discover any issues.