Introduction.

After conducting research on popular Wordpress plugins I discovered a logic-bug in BBPress which is installed on over 300,000+ websites. The found vulnerability was identified to be privilege-escalation, I was assigned CVE-2020-13693 and a X,XXX payout from Wordpress on Hackerone. Due to the severity and ease of exploitation, this was assigned a CVSS of 9.8. This vulnerability as we’ll see below was possible because of a white-box approach with the help of Nathan Hrncirik setting up a virtual wordpress environment.

Exploitation and Impact.

By simply adding the bbp-forums-role parameter with the value of bbp_keymaster to the signup request you can effectively make the newly created user a “Keymaster” which is a forum administrator, gaining complete forum control. The impact of this is huge, by gaining Keymaster access one can delete forum activities, import/export forum users, and create moderators. There is however a couple of conditions that need to be met to exploit this, the first being that user registration needs to be enabled on a site, allowing the creating of new forum users, second a BBPress register form (shortcode [bbp-register]) needs to be embedded so a nonce can be retrieved. Below is a screenshot of me using Burpsuite to manually exploit the vulnerability. CVE After sending the request, if we navigate to the dashboard we can see our newly created user has the Keymaster role. CVE

Initial Discovery.

After analyzing the user registration section of the code, it was discovered that the add_filter was being triggered on the signup_user_meta tag and was passed into the bbp_user_add_role_to_signup_meta function which is called during user registration in /includes/core/filters.php. In Wordpress add_filter is used as a “hook” in order to change or alter internal data at runtime. This was interesting because according to the Wordpress developer documentation signup_user_meta is a filter that’s used for role manipulation and adding user metadata properties during user signup. This means BBPress was altering the metadata roles of a user as the user registers. This really isn’t surprising as BBPress is forum software, and there’s a separation of roles for users, moderators, and administrators.

1
2
// User Creation
add_filter( 'signup_user_meta', 'bbp_user_add_role_to_signup_meta', 10 );

After investigation the add_filter hook I examined the bbp_user_add_role_to_signup_meta function located in /includes/user/signups.php which handles when the tag was called. This function takes the post parameter bbp-forums-role and sees if its in a dynamic role array returned from bbp_get_dynamic_roles(). Looking at this the only thing that’s needed to subvert the logic of the program is to simply send the parameter of the bbp-forums-role post request with a valid role.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function bbp_user_add_role_to_signup_meta( $meta = array() ) {

	// Posted role
	$forum_role = isset( $_POST['bbp-forums-role'] )
		? sanitize_key( $_POST['bbp-forums-role'] )
		: bbp_get_default_role();

	// Role keys
	$roles = array_keys( bbp_get_dynamic_roles() );

	// Bail if posted role is not in dynamic roles
	if ( empty( $forum_role ) || ! in_array( $forum_role, $roles, true ) ) {
		return $meta;
	}

	// Add role to meta
	$meta['bbp_new_role'] = $forum_role;

	// Return meta
	return $meta;
}

The bbp_get_dynamic_roles function in /includes/core/capabilities.php iterates through te BBPress roles and creates them into a standardized array and applies it as a tag. In order to now successfully add a role, we have to figure out what the name of the Keymaster role is.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function bbp_get_dynamic_roles() {

	// Defaults
	$to_array = array();
	$roles    = bbpress()->roles;

	// Convert WP_Roles objects to arrays
	foreach ( $roles as $role_id => $wp_role ) {
		$to_array[ $role_id ] = (array) $wp_role;
	}

	// Filter & return
	return (array) apply_filters( 'bbp_get_dynamic_roles', $to_array, $roles );
}

The bbp_get_keymaster_role() function in /includes/core/capabilities.php sets the bbp_get_keymaster_role role equal to bbp_keymaster, meaning that we need to add bbp_keymaster at the end of our post request in order to sucessfully register a keymaster user.

1
2
3
4
5
function bbp_get_keymaster_role() {

	// Filter & return
	return apply_filters( 'bbp_get_keymaster_role', 'bbp_keymaster' );
}

Conclusion.

The BBPress team was very quick to issue a patch, in the form of 2.6.5 successfully validating the roles that are being added. Patch Notes for BBPress 2.6.5. If you enjoyed this post, follow me on Twitter for more content in the future.