3 Jun 2019

Privilege Escalation Vulnerability Only Partially Fixed in WordPress Plugin Ultimate Member Due to Use of is_admin()

We can’t emphasize enough that you should not use the plugin Ultimate Member as the plugin has been riddled with security vulnerabilities including one that was widely exploited last year and was slow to be fixed, due to what appears to be a lack of interest by the developer in getting it secure. That lack of interest is particularly problematic due to the fact that the plugin has 100,000+ active installations according to wordpress.org. The latest vulnerability found in it is yet another reminder of that, as the developer attempted to fix a serious vulnerability, but used the wrong code, so there is still a vulnerability, though less easily exploited. The continuation of the vulnerability also involves a security failure in WordPress that was warned about back in February of 2011, but still hasn’t been resolved despite being continually being implicated in widely exploited vulnerabilities.

The situation is also is yet another reminder why actually checking out and testing out claimed fixed vulnerabilities is important, so you don’t incorrectly believe that an unfixed vulnerability that is more widely known about, since it has been noted to have been fixed, has been fixed. That is something we do, but clearly other data sources on WordPress plugin vulnerabilities competing with our service don’t do.

One of the changelogs entries for the latest version of the plugin is “Fixed security vulnerability with registration form”. We haven’t been able to find any public disclosure of who was behind finding that. Looking at the changes made in that version we saw code that was extremely alarming.

In the previous version of the plugin in the function profile_update() was this code:

484
485
486
487
488
489
if ( ! empty( $_POST['um-role'] ) ) {
	$new_roles = array_merge( $new_roles, array( $_POST['um-role'] ) );
	if ( ! user_can( $user_id, $_POST['um-role'] ) ) {
		UM()->roles()->set_role( $user_id, $_POST['um-role'] );
	}
}

That code allows adding an arbitrary WordPress role to a user, allowing, for example, a low level users to become an Administrator.

The new version restricts access to that code to if the function is_admin() is true, which it seems like the developer might be incorrectly assuming tells you if the user making the request is an Administrator, when it just tells if an admin page is being accessed:

488
489
490
491
492
493
494
495
if ( is_admin() ) {
	if ( ! empty( $_POST['um-role'] ) ) {
		$new_roles = array_merge( $new_roles, array( $_POST['um-role'] ) );
		if ( ! user_can( $user_id, $_POST['um-role'] ) ) {
			UM()->roles()->set_role( $user_id, $_POST['um-role'] );
		}
	}
}

That function runs when the “profile_update” action is run:

76
add_action( 'profile_update', array( &$this, 'profile_update' ), 10, 2 ); // user_id and old_user_data

Normally that would mean that the is_admin() check would always be true, since someone would be updating their profile from an admin page, but how this plugin works is that by default it restricts lower level users to only the frontend of the website and they update their profile from that. There are multiple scenarios where is_admin() would still be true when updating a profile. One would be if another plugin allows updating a user’s profile through an AJAX function, since that will also cause is_admin() to be true. Another would be if this plugin’s settings are changed to allow low level users’ access to the admin area of WordPress.

The confusion over is_admin() was warned about to the WordPress developers in February of 2011 before the function even made it in to a production version of WordPress, but the response after two years was:

As for the is_*_admin() methods, this ticket was totally ignored for 2 years, and those have been in use for a long time now, so now I really think this patch is completely pointless now, and not worth doing.

Despite that confusion continuing to be implicated in widely exploited vulnerabilities nothing has been done about that. The ultimate blame for that seems to fall on the person in control of WordPress, Matt Mullenweg, since he has put in place people in security roles that don’t seem like they should be in those and he and those people have been unwilling to work with others to address security problems like this. Through January there was someone who was funded by GoDaddy to be “WordPress Core Security Team Lead”, which seems like a person who should have gotten that worked on. They left that role to be GoDaddy’s head of WordPress Ecosystem & Community, which is the kind of job switch you wouldn’t expect for someone that actually had the necessary expertise to be in a security role. We haven’t been able to find a public indication that anyone replaced them.

There is similar code in other places in the plugin’s code.

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:

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.

Proof of Concept

When logged in as a Subscriber with the Subscriber role set to be able access to the admin area of WordPress in Ultimate Members settings, add the following line to the form on WordPress’ Profile page, /wp-admin/profile.php, and then update the profile. The user will now have the Administrator role.

<input type="hidden" name="um-role" value="administrator" />

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.

Plugin Security Scorecard Grade for Ultimate Member

Checked on November 23, 2024
C+

See issues causing the plugin to get less than A+ grade

Leave a Reply

Your email address will not be published.