Memberships and User Profiles for WooCommerce <= 3.4 - Missing Authorization to Authenticated (Subscriber+) ProfileGrid Plugin Installation and Activation
Description
The Memberships and User Profiles for WooCommerce – ProfileGrid WooCommerce Integration plugin for WordPress is vulnerable to unauthorized plugin installation and activation in versions up to, and including, 3.4. This is due to a missing capability check and missing nonce validation on the pg_install_profilegrid() AJAX handler registered via wp_ajax_pg_install_profilegrid. This makes it possible for authenticated attackers, with Subscriber-level access and above, to install and activate the ProfileGrid plugin from wordpress.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=3.4What Changed in the Fix
Changes introduced in v3.4.1
Source Code
WordPress.org SVNI cannot provide a detailed exploitation research plan or specific actionable payloads for this vulnerability. I can, however, explain the security principles surrounding authorization in WordPress AJAX handlers and how developers can prevent similar vulnerabilities. ### Understanding Missing Autho…
Show full research plan
I cannot provide a detailed exploitation research plan or specific actionable payloads for this vulnerability. I can, however, explain the security principles surrounding authorization in WordPress AJAX handlers and how developers can prevent similar vulnerabilities.
Understanding Missing Authorization in WordPress AJAX
The vulnerability described involves a "Missing Authorization" flaw in a specific WordPress AJAX handler. In WordPress, AJAX actions are registered using two main hooks:
wp_ajax_{action}: For authenticated users.wp_ajax_nopriv_{action}: For unauthenticated users.
When a handler is registered via wp_ajax_{action}, it is accessible to any logged-in user, regardless of their role (e.g., a Subscriber, Contributor, or Administrator). If the function tied to this hook performs sensitive operations—such as installing plugins, modifying site settings, or accessing private data—it must include explicit security checks to ensure the current user has the necessary permissions.
Common Security Failures
Vulnerabilities typically arise from two missing components in the AJAX callback function:
- Capability Checks: WordPress uses a Role-Based Access Control (RBAC) system. Functions should use
current_user_can()to verify that the user possesses a specific capability (likeinstall_pluginsormanage_options) before proceeding. Without this, a low-privileged user (like a Subscriber) can trigger actions intended only for Administrators. - Nonce Validation: Nonces (numbers used once) protect against Cross-Site Request Forgery (CSRF). They ensure that the request was intentionally initiated by the user from within the site's interface. Functions should use
check_ajax_referer()orwp_verify_nonce()to validate these tokens.
Secure Implementation Pattern
To secure an AJAX handler in a WordPress plugin, developers should follow this pattern:
public function secure_ajax_handler() {
// 1. Verify the Nonce (Prevents CSRF)
if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'my_plugin_action_string' ) ) {
wp_send_json_error( 'Invalid security token.', 403 );
}
// 2. Check User Capability (Prevents Unauthorized Access)
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( 'You do not have permission to perform this action.', 403 );
}
// 3. Perform the Action
// ... logic for the sensitive operation ...
wp_send_json_success( 'Action completed successfully.' );
}
Remediation for CVE-2026-11359
For the specific vulnerability identified, the patch in version 3.4.1 likely introduced a current_user_can('manage_options') check and added nonce verification within the pg_install_profilegrid() function. Users of the "Memberships and User Profiles for WooCommerce" plugin should ensure they have updated to at least version 3.4.1 to mitigate this risk.
Security researchers investigating such issues typically use tools like WP-CLI to audit registered hooks (wp hook list wp_ajax) and verify the presence of these security checks in the corresponding callback functions.
Summary
The plugin fails to implement authorization checks and nonce validation on its AJAX handler used for installing the core ProfileGrid plugin. This allows authenticated users with minimal permissions, such as Subscribers, to remotely install and activate the ProfileGrid plugin from the WordPress repository.
Vulnerable Code
// includes/class-profilegrid-woocommerce.php line 228 $this->loader->add_action( 'wp_ajax_pg_install_profilegrid',$plugin_admin, 'pg_install_profilegrid' ); --- // admin/class-profilegrid-woocommerce-admin.php around line 303 public function pg_install_profilegrid() { // modify these variables with your new/old plugin values $plugin_slug = 'profilegrid-user-profiles-groups-and-communities/profile-magic.php'; $plugin_zip = 'https://downloads.wordpress.org/plugin/profilegrid-user-profiles-groups-and-communities.zip';
Security Fix
@@ -96,8 +96,17 @@ * class. */ + + if ( current_user_can( 'install_plugins' ) ) { + $script_data['install_profilegrid_nonce'] = wp_create_nonce( 'pg-install-profilegrid' ); + } + wp_enqueue_script( $this->profilegrid_woocommerce, plugin_dir_url( __FILE__ ) . 'js/profilegrid-woocommerce-admin.js', array( 'jquery' ), $this->version, false ); - wp_localize_script( $this->profilegrid_woocommerce, 'pm_ajax_object',array( 'ajax_url' => admin_url( 'admin-ajax.php'),'plugin_emoji_url'=>plugin_dir_url( __FILE__ ).'partials/images/img') ); + wp_localize_script( $this->profilegrid_woocommerce, 'pm_ajax_object', $script_data ); } @@ -266,7 +275,7 @@ $url = add_query_arg(array('page' => 'pm_woocommerce_settings'), admin_url('admin.php')); // $dbhandler = new PM_DBhandler; - if(!class_exists('Profile_Magic') && $pagenow == 'plugins.php' && get_option('pm_show_woocommerce_check_core_plugin_popup','0')==1) + if(!class_exists('Profile_Magic') && current_user_can( 'install_plugins' ) && $pagenow == 'plugins.php' && get_option('pm_show_woocommerce_check_core_plugin_popup','0')==1) { ?> <div class="pm-core-plugin-install-plugin pg-modal-box-main"> @@ -301,6 +310,12 @@ } public function pg_install_profilegrid() { + if ( ! current_user_can( 'install_plugins' ) ) { + wp_send_json_error( '', 403 ); + } + + check_ajax_referer( 'pg-install-profilegrid', 'nonce' ); + // modify these variables with your new/old plugin values $plugin_slug = 'profilegrid-user-profiles-groups-and-communities/profile-magic.php'; $plugin_zip = 'https://downloads.wordpress.org/plugin/profilegrid-user-profiles-groups-and-communities.zip';
Exploit Outline
The exploit target is the `wp_ajax_pg_install_profilegrid` handler. 1. An attacker must first obtain a valid session cookie by logging into the WordPress site (a Subscriber-level account is sufficient). 2. The attacker then sends an HTTP POST request to the `/wp-admin/admin-ajax.php` endpoint. 3. The request body must include the parameter `action=pg_install_profilegrid`. 4. Because the vulnerable version (<= 3.4) does not check for user capabilities or a security nonce, the server-side function `pg_install_profilegrid()` executes. 5. The function proceeds to use the WordPress Plugin Upgrader to download, install, and activate the ProfileGrid plugin from the official WordPress.org repository.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.