Critical Authentication Bypass Vulnerability Patched in Booster for WooCommerce
On July 30, 2021 the Wordfence Threat Intelligence team initiated the responsible disclosure process for a vulnerability that we discovered in Booster for WooCommerce, a WordPress plugin installed on over 80,000 sites. This flaw made it possible for an attacker to log in as any user, as long as certain options were enabled in the plugin.
Wordfence Premium users received a firewall rule to protect against any exploits targeting this vulnerability on July 30, 2021. Sites still using the free version of Wordfence will receive the same protection on August 29, 2021.
We initially reached out to the plugin vendor on July 30, 2021. After receiving confirmation of an appropriate communication channel a few days later on August 2, 2021, we provided the full disclosure details. The vendor quickly acknowledged the report and a patch was released on August 11, 2021 in version 5.4.4.
We strongly recommend updating immediately to the latest patched version of Booster for WooCommerce, which is version 5.4.4 at the time of publication.
Affected Plugin: Booster for WooCommerce
Plugin Slug: woocommerce-jetpack
Affected Versions: <= 5.4.3
CVE ID: CVE-2021-34646
CVSS Score: 9.8 (Critical)
CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Researcher/s: Chloe Chamberland
Fully Patched Version: 5.4.4
Booster for WooCommerce is an addon plugin for WooCommerce designed to enhance its functionality through the use of various modules that site owners can enable and disable at any point. One module that the plugin offers is an `Email Verification` module, which adds a requirement for users to verify their email after they have registered on the site.
Unfortunately, we found that this feature was insecurely implemented, which made it possible for an attacker to impersonate any user and send a verification request that could allow the attacker to easily recreate the token needed to “verify” the targeted user’s email, and be automatically logged in as that user.
A Closer Look at The Exploit
In order to exploit this vulnerability, an attacker would need to execute two actions. The first action an attacker would need to perform involves sending a request to the vulnerable site’s home URL with the wcj_user_id
parameter set to the user ID that the attacker would like to impersonate. This would likely be set to a user ID of 1 because the first user account typically created on WordPress sites is the administrative user account and this is rarely changed.
} elseif ( isset( $_GET['wcj_user_id'] ) ) { $this->reset_and_mail_activation_link( $_GET['wcj_user_id'] ); wc_add_notice( do_shortcode( wcj_get_option( 'wcj_emails_verification_email_resend_message', __( '<strong>Success:</strong> Your activation email has been resent. Please check your email.', 'woocommerce-jetpack' ) ) ) ); }
Once the request was sent, the reset_and_mail_activation_link()
function was triggered. This retrieved the supplied user_id
and generated a code for the user that was used to verify the email address. The function then triggered an email to be sent to the user with the generated verification link that could be used to verify the email address.
The core of the flaw lies here where the verification code was simply an MD5 hash of the time of the request. This made it possible for an attacker to easily recreate a valid verification code without access to the targeted user’s email account based on the time they sent a verification request for any given user.
function reset_and_mail_activation_link( $user_id ) { $user_info = get_userdata( $user_id ); $code = md5( time() ); $url = add_query_arg( 'wcj_verify_email', base64_encode( json_encode( array( 'id' => $user_id, 'code' => $code ) ) ), wc_get_page_permalink( 'myaccount' ) ); $email_content = do_shortcode( apply_filters( 'booster_option', __( 'Please click the following link to verify your email:<br><br><a href="%verification_url%">%verification_url%</a>', 'woocommerce-jetpack' ), get_option( 'wcj_emails_verification_email_content', __( 'Please click the following link to verify your email:<br><br><a href="%verification_url%">%verification_url%</a>', 'woocommerce-jetpack' ) ) ) ); $email_content = str_replace( '%verification_url%', $url, $email_content ); $email_subject = do_shortcode( apply_filters( 'booster_option', __( 'Please activate your account', 'woocommerce-jetpack' ), get_option( 'wcj_emails_verification_email_subject', __( 'Please activate your account', 'woocommerce-jetpack' ) ) ) ); update_user_meta( $user_id, 'wcj_is_activated', '0' ); update_user_meta( $user_id, 'wcj_activation_code', $code );
Once the attacker had sent an email verification request for their target user, they would then need to perform the second action which involved crafting the URL to “verify” the email. This would be the site’s home URL with the wcj_verify_email
parameter set to a base64 JSON-encoded payload where the JSON-encoded body contains the target user ID set at the `id
` value and the `code
` value set as the generated MD5 hash of the time that the email verification request was made.
If the wcj_emails_verification_redirect_on_success
option was set to yes and the data sent in the wcj_verify_email
parameter was valid, then the wp_set_current_user
and wp_set_auth_cookie
functions would run and generate an authenticated session as the targeted user, thus allowing the attacker to bypass any authentication and gain access to any account they chose.
} elseif ( isset( $_GET['wcj_verify_email'] ) ) { $data = json_decode( base64_decode( $_GET['wcj_verify_email'] ), true ); if ( ! empty( $data['id'] ) && ! empty( $data['code'] ) && get_user_meta( $data['id'], 'wcj_activation_code', true ) == $data['code'] ) { update_user_meta( $data['id'], 'wcj_is_activated', '1' ); if ( 'yes' === wcj_get_option( 'wcj_emails_verification_redirect_on_success', 'yes' ) ) { wp_set_current_user( $data['id'] ); wp_set_auth_cookie( $data['id'] ); } $url = ( '' != ( $custom_url = wcj_get_option( 'wcj_emails_verification_redirect_on_success_custom_url', '' ) ) ? $custom_url : wc_get_page_permalink( 'myaccount' ) ); wp_safe_redirect( add_query_arg( 'wcj_verified_email', $_GET['wcj_verify_email'], $url ) ); exit;
As such, an attacker could exploit this vulnerability to gain administrative access on sites running a vulnerable version of the plugin and effectively take-over the site.
This vulnerability requires the `Email Verification` module to be enabled and the `Login User After Successful Verification` setting to be enabled, which is by default, to be successfully exploited on sites running the plugin.
Disclosure Timeline
July 30, 2021 – Conclusion of the plugin analysis that led to the discovery of an authentication bypass vulnerability in the Booster for WooCommerce WordPress plugin. We develop a firewall rule to protect Wordfence customers and release it to Wordfence Premium users. We initiate contact with the plugin vendor.
August 2, 2021 – The vendor confirms the inbox for handling disclosure. We send over full disclosure details.
August 4, 2021 – The vendor confirms they have received the details and will begin working on a fix.
August 11, 2021 – A newly updated version of the plugin is released containing sufficient patches.
August 29, 2021 – Wordfence free users receive firewall rule.
Conclusion
In today’s post, we detailed a flaw in Booster for WooCommerce that granted attackers the ability to bypass authentication and log in as any existing site user, including administrative users, that could be used to take over a vulnerable WordPress site. This flaw has been fully patched in version 5.4.4. We recommend that WordPress users immediately update to the latest version available, which is version 5.4.4 at the time of this publication.
Wordfence Premium users received a firewall rule to protect against any exploits targeting this vulnerability on July 30, 2021. Sites still using the free version of Wordfence will receive the same protection on August 29, 2021.
If you know a friend or colleague who is using this plugin on their site, we highly recommend forwarding this advisory to them to help keep their sites protected as this is a critical vulnerability that can lead to full site takeover.
Click here to join the WordPress Security mailing list and receive vulnerability reports like this the moment they are published.
Comments
4:52 pm
Good job, Wordfence! I'm always amazed by you capacity to spot vulnerabilities and get them fixed quickly. Your tireless contribution to the entire WordPress community is simply priceless.
9:57 pm
Thank you for updating us. It really help me to secure my website
2:33 am
If I have 2fa authentication enabled, I should have been protected in case of an attack via this exploit correct?
8:04 am
Hi Lou,
Unfortunately, 2FA would not protect your site against this exploit because it completely bypasses any normal authentication mechanisms. I recommended updating to the latest version available of Booster for WooCommerce to be protected against this issue.
9:56 am
I see, thankfully I am not using it, goes to show plugin vulnerabilities really are the main funnel to a compromised system, thank you for your work :)
3:05 am
I also just checked Booster Plus for WooCommerce, and that looks to also be vulnerable, with the latest update fixing it. I didn't see that listed in this announcement, so I wanted to share that information.
9:39 am
And to think - one simple decision (to use a random value to generate the confirmation code) would've made the entire attack useless.
Yes, it saved a database field (since you can simply MD5() the timestamp again at verification), but at the same time - it also allows an easily-guessable value to be used for *security*. And the one thing you *never* want for *security*, is a value that's easy to guess.
Sometimes being clever works against you.
Lesson to take away: always use random values at least as part of your token. A token is meant to REPRESENT something, not to encode it. It may not be immediately obvious (though here, it kinda is...) how knowing the token value could compromise security, but it's the sort of thing one tends to *forget* down the line, and it could transmute into an attack vector with code you'll add six months from now...
9:44 am
Now that I look at the code again, it didn't even save that database field, because the code is still inserted as user meta... seriously?
What did using the request time as the code accomplish? It didn't even simplify any of the algo, since that call to time() could just as easily be replaced with random_bytes(16) and it wouldn't change a thing...
11:09 am
So how do you fix this once they've infiltrated your site?
8:32 am
Hi there,
I'd recommend following this guide to clean-up your site if it has been compromised. If your site was exploited by this vulnerability specifically, then you will want to make sure you update the plugin immediately so it does not happen again and make sure to change all of your user's passwords just in case the attacker changed any of the passwords to maintain persistence. Further, I would recommend checking to make sure no rogue user accounts have been added to your site and, if they have, make sure to delete them immediately.
2:37 pm
I see the firewall rule came into effect for this on August 29. To be clear, is there a Wordfence plugin update that goes along with that, or should we wait for the plugin to know this vulnerability is patched by Wordfence, also?
2:59 pm
Hi Ryan!
The rule was automatically added to the list of firewall rules for free users on August 29th, it does not require a plugin update.