The plugin is affected by an Unauthenticated Insecure Direct Object Reference (IDOR) to Arbitrary User Email Change vulnerability, witch leads to User Password Reset, which leads to Privilege Escalation. The plugin has an insecurely used variable allowing to change the user email, and gain unauthorized access.


Let’s check the plugin

The processing() method in the WCFMvm_Memberships_Registration_Controller class handles the memberships registration with the following code:

if ( isset( $wcfm_membership_registration_form_data['member_id'] ) && $wcfm_membership_registration_form_data['member_id'] != 0 ) {
	$member_id = absint( $wcfm_membership_registration_form_data['member_id'] );
	$is_update = true;

As we can see, it is possible to specify the user id value in the request, and in this case it will not be user addition, but user update.

$user_email = sanitize_email( $wcfm_membership_registration_form_data['user_email'] );

It is also possible to specify the email in the request.

$user_data = array(
	'user_email'    => $user_email,
	'ID'            => $member_id,
if ( $is_update ) {
	if ( ! wcfm_is_vendor() ) {
		$member_id = wp_update_user( $user_data );

The user data used to update the user also includes the user id (which is the member id) and the email. Which means that it is possible to change any user’s email.

If we have changed the user’s email, we can request a password reset, which will be sent to our email, and we can change the password.


Let’s see how we can exploit this vulnerability

We only need to send a POST request to exploit this vulnerability.

The HTTP request:

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded


We can find the nonce in the wcfm_params.wcfm_ajax_nonce JavaScript object.


The exploit script

I created a Python script that which updates the specified user’s email:


How to use:

python3 --website_url="http://localhost/" --email="[email protected]" --user_id=1

Run the above command in the Linux terminal.