Wordfence Security team discovered a vulnerability in WP Data Access, a WordPress plugin that is installed on over 10,000 sites.

This flaw makes it possible for authenticated attackers to grant themselves administrative privileges via a profile update if the targeted site has the ‘Role Management’ setting enabled.

The WP Data Access plugin for WordPress is vulnerable to privilege escalation in versions up to, and including, 5.3.7. This is due to a lack of authorization checks on the multiple_roles_update function. This makes it possible for authenticated attackers, with minimal permissions such as a subscriber, to modify their user role by supplying the ‘wpda_role[]‘ parameter during a profile update. This requires the ‘Enable role management’ setting to be enabled for the site.

WP Data Access is a WordPress plugin designed to make data table creation in WordPress more intuitive and easier to manage for site owners. One feature of the plugin is the ability to enable role management, which makes it possible for a site owner to create custom roles and assign multiple roles to different users. Unfortunately, this functionality was insecurely implemented making it possible for authenticated users to assign any role to themselves, including the administrative role.

Taking a closer look at the code, the team saw that the ‘multiple_roles_update‘ function used to assign a user’s new roles upon updating a profile is hooked via ‘’profile_update‘’. This hook is triggered immediately after any user profile is updated and it does not perform any sort of authorization checks on the user performing the action. As such, this means that any update to a user’s profile, including on the profile.php page, will invoke the hooked function ‘multiple_roles_update‘.

READ
Meta Takes Action Against Organized Online Scams, Removing Over 2 Million Accounts in 2024

This makes it possible for any authenticated users with an account, such as subscribers, to invoke the ‘multiple_roles_update‘ function.

229$this->loader->add_action( 'profile_update', $wpda_roles, 'multiple_roles_update');

If the associated function had a capability check, then it may have prevented these users from fully executing the function, however, that was not the case. Reviewing the hooked function, the team see a check verifying that the role management setting is enabled, but nothing more. The function then determines the user and looks for the ‘wpda_role‘ array parameter from a given request. If present, it will process the supplied roles and add the role and applicable permissions to the user retrieved in the first step.

This made it possible for authenticated users, such as a subscriber, to make profile updates to supply the ‘wpda_role‘ array parameter with any desired roles, such as administrator, during a profile update that would be granted immediately upon saving of the profile updates.

public function multiple_roles_update( $user_id ) {
   if ( ! $this->is_role_management_enabled ) {
      return;
   }
 
   $wp_user = new \WP_User( $user_id );
   if ( isset( $wp_user->data->user_login ) ) {
      $user_login = $wp_user->data->user_login;
      // Get access to editable roles
      global $wp_roles;
      if ( isset( $_REQUEST['wpda_role'] ) && is_array( $_REQUEST['wpda_role'] ) ) {
         // Process roles
         $sanitized_roles = array();
         foreach ( $_REQUEST['wpda_role'] as $new_user_role ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
            $sanitized_new_user_role = sanitize_text_field( wp_unslash( $new_user_role ) ); // input var okay.
            $wp_user->add_role( $sanitized_new_user_role );
            $sanitized_roles[ $sanitized_new_user_role ] = true;
         }
 
         // Remove unselected roles
         foreach ( $wp_roles->roles as $role => $val ) {
            if ( ! isset( $sanitized_roles[ $role ] ) ) {
               $wp_user->remove_role( $role );
            }
         }
      } else {
         // BUG!!! REMOVED!!!
         // When plugin role management is enabled, this removes all user roles when a user updates his profile.
         // foreach ( $wp_roles->roles as $role => $val ) {
         // $wp_user->remove_role( $role );
         // }
      }
   }
}

As with any Privilege Escalation vulnerability, this can be used for complete site compromise. Once an attacker has gained administrative user access to a WordPress site they can then manipulate anything on the targeted site as a normal administrator would. This includes the ability to upload plugin and theme files, which can be malicious zip files containing backdoors, and modify posts and pages which can be leveraged to redirect site users to other malicious sites.

READ
French Hospital Data Breach Exposes 750,000 Patients' Medical Records