[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fnZT-wLRT9LYqldpeSjV8mfhQ1EtHALDvPRzDjM-GkvQ":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":26,"research_verified":27,"research_rounds_completed":28,"research_plan":29,"research_summary":30,"research_vulnerable_code":31,"research_fix_diff":32,"research_exploit_outline":33,"research_model_used":34,"research_started_at":35,"research_completed_at":36,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":27,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":27,"source_links":37},"CVE-2026-7641","import-and-export-users-and-customers-authenticated-subscriber-privilege-escalation-via-multisite-capability-meta-fields","Import and export users and customers \u003C= 2.0.8 - Authenticated (Subscriber+) Privilege Escalation via Multisite Capability Meta Fields","The Import and export users and customers plugin for WordPress is vulnerable to Privilege Escalation in all versions up to and including 2.0.8 via the `save_extra_user_profile_fields()` function. This is due to an incomplete blocklist that correctly restricts capability meta keys for the primary site (e.g., `wp_capabilities`, `wp_user_level`) but fails to block the equivalent meta keys for any other subsite in a WordPress Multisite network (e.g., `wp_2_capabilities`, `wp_2_user_level`), allowing these keys to pass the `in_array()` check and be written directly to user meta via `update_user_meta()`. This makes it possible for authenticated attackers, with Subscriber-level access and above, to escalate their privileges to Administrator on any subsite within the Multisite network by submitting a crafted profile update to `\u002Fwp-admin\u002Fprofile.php`. Exploitation requires that an administrator has previously imported a CSV file containing multisite-prefixed capability column headers and has enabled the 'Show fields in profile?' option, which causes those keys to be stored in the `acui_columns` option and exposed as editable fields on the user profile page.","import-users-from-csv-with-meta",null,"\u003C=2.0.8","2.0.9","high",8.8,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:H\u002FI:H\u002FA:H","Improper Privilege Management","2026-05-01 16:14:05","2026-05-02 04:27:46",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F368cff00-6a86-443e-aec4-4115a229a3c1?source=api-prod",1,[22,23,24,25],"classes\u002Fimport.php","classes\u002Fmultisite.php","import-users-from-csv-with-meta.php","readme.txt","researched",false,3,"# Exploitation Research Plan - CVE-2026-7641\n\n## 1. Vulnerability Summary\nThe **Import and export users and customers** plugin (\u003C= 2.0.8) is vulnerable to privilege escalation in WordPress Multisite environments. The vulnerability exists in the `save_extra_user_profile_fields()` function (typically hooked to `personal_options_update` and `edit_user_profile_update`). \n\nThe plugin allows users to update \"extra profile fields\" that were previously defined during a CSV import. While it attempts to block sensitive meta keys like `wp_capabilities` and `wp_user_level` for the primary site, it fails to account for the naming convention of capability keys on other sites in a Multisite network (e.g., `wp_2_capabilities`, `wp_2_user_level`). Consequently, a Subscriber can submit a profile update containing these keys to grant themselves Administrator privileges on any subsite in the network.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** `\u002Fwp-admin\u002Fprofile.php` (Standard WordPress profile update).\n- **HTTP Method:** `POST`.\n- **Authentication Level:** Authenticated (Subscriber or higher).\n- **Vulnerable Parameter:** Any `$_POST` key corresponding to a subsite capability meta key (e.g., `wp_2_capabilities`).\n- **Preconditions:**\n    1. The WordPress installation must be a **Multisite** network with at least one subsite (e.g., Blog ID 2).\n    2. An administrator must have previously imported a CSV containing a column header matching a subsite capability key (e.g., `wp_2_capabilities`).\n    3. The plugin option **\"Show fields in profile?\"** must be enabled in the \"Extra profile fields\" tab (`tab=columns`). This causes the key to be saved in the `acui_columns` option.\n\n## 3. Code Flow\n1. **Registration:** The plugin registers `save_extra_user_profile_fields()` to the `personal_options_update` and `edit_user_profile_update` hooks.\n2. **Key Retrieval:** When a user updates their profile, the function retrieves the list of allowed \"extra fields\" from the `acui_columns` option.\n3. **Filtering:** The function iterates through the `$_POST` data. It uses `in_array()` to check if the key is in a restricted blocklist.\n4. **The Flaw:** The blocklist contains hardcoded strings: `['wp_capabilities', 'wp_user_level']`. In a Multisite setup, the capability key for Blog ID 2 is `wp_2_capabilities`. This key is **not** in the blocklist.\n5. **Update:** Since the key `wp_2_capabilities` is present in the `acui_columns` option (due to the admin import) and not in the blocklist, the plugin calls `update_user_meta( $user_id, 'wp_2_capabilities', $_POST['wp_2_capabilities'] )`.\n\n## 4. Nonce Acquisition Strategy\nThis exploit targets the standard WordPress profile update, which uses the standard WordPress `_wpnonce`.\n\n1. **Shortcode\u002FPage:** No specific plugin shortcode is required for the exploit itself, as it uses the standard `\u002Fwp-admin\u002Fprofile.php`.\n2. **Acquisition:**\n    - Login as the Subscriber user.\n    - Navigate to `https:\u002F\u002F\u003Ctarget>\u002Fwp-admin\u002Fprofile.php`.\n    - Extract the nonce from the hidden input field: `\u003Cinput type=\"hidden\" id=\"_wpnonce\" name=\"_wpnonce\" value=\"[NONCE_VALUE]\" \u002F>`.\n3. **Browser Eval:**\n   ```javascript\n   \u002F\u002F To be run via browser_eval\n   document.querySelector('#_wpnonce').value\n   ```\n\n## 5. Exploitation Strategy\n\n### Step 1: Pre-Exploit Setup (Admin)\n1. Ensure Multisite is enabled and a subsite (ID 2) exists.\n2. Create a CSV file named `setup.csv`:\n   ```csv\n   user_login,user_email,wp_2_capabilities\n   victim_sub,victim@example.com,\"a:1:{s:10:\"\"subscriber\"\";b:1;}\"\n   ```\n3. As Admin, go to `Tools -> Import and export users and customers`.\n4. Upload and import `setup.csv`.\n5. Go to the **Extra profile fields** tab (`tab=columns`).\n6. Enable **\"Show fields in profile?\"** and save. This ensures `wp_2_capabilities` is added to the `acui_columns` option and rendered on the profile page.\n\n### Step 2: Escalation (Subscriber)\n1. Login as the Subscriber (`victim_sub`).\n2. Navigate to `\u002Fwp-admin\u002Fprofile.php`.\n3. Perform a `POST` request to `\u002Fwp-admin\u002Fprofile.php` with the following payload:\n   - `action`: `update`\n   - `user_id`: `[SUBSCRIBER_ID]`\n   - `_wpnonce`: `[EXTRACTED_NONCE]`\n   - `wp_2_capabilities`: `a:1:{s:13:\"administrator\";b:1;}`\n   - `wp_2_user_level`: `10`\n\n**Payload Details:**\n- **URL:** `https:\u002F\u002F\u003Ctarget>\u002Fwp-admin\u002Fprofile.php`\n- **Content-Type:** `application\u002Fx-www-form-urlencoded`\n- **Body:**\n  `action=update&user_id=[ID]&_wpnonce=[NONCE]&wp_2_capabilities=a%3A1%3A%7Bs%3A13%3A%22administrator%22%3Bb%3A1%3B%7D&wp_2_user_level=10&from=profile&checkuser_id=[ID]`\n\n## 6. Test Data Setup\n- **Multisite:** Subsite with ID `2`.\n- **User:** A user with Subscriber role on the main site (ID 1) and subsite (ID 2).\n- **Plugin Config:** \n    - `acui_columns` option must contain `wp_2_capabilities`.\n    - `acui_settings` (or the specific option for \"Show fields in profile\") must be set to `true`.\n\n## 7. Expected Results\n1. The profile update request returns a `302 Redirect` back to `profile.php?updated=1`.\n2. The user's metadata in the `wp_usermeta` table for the key `wp_2_capabilities` is updated to the serialized Administrator role object.\n3. The user's `wp_2_user_level` is updated to `10`.\n\n## 8. Verification Steps\nAfter the `POST` request, verify using WP-CLI:\n```bash\n# Check the capabilities of the user on subsite 2\nwp user get victim_sub --fields=capabilities --url=http:\u002F\u002F[subsite_domain_or_path]\n\n# Verify the meta directly\nwp user meta get [USER_ID] wp_2_capabilities\nwp user meta get [USER_ID] wp_2_user_level\n```\n\n## 9. Alternative Approaches\nIf the plugin uses a specific AJAX handler for profile updates (though the description points to `profile.php`), check for `wp_ajax_acui_update_profile_meta` or similar registrations in `classes\u002Fimport.php`. If an AJAX handler is used:\n1. Identify the AJAX action name.\n2. Extract the nonce via `window.acui_import_js_object.nonce` (if localized).\n3. Submit a `POST` to `\u002Fwp-admin\u002Fadmin-ajax.php`.\n\nGiven the source provided, `ACUI_Import::enqueue` localizes `acui_import_js_object`, but it only contains URLs and translation strings. This reinforces that the vulnerability likely leverages standard WordPress form submissions which are caught by the plugin's hooks.","The plugin is vulnerable to privilege escalation in WordPress Multisite environments because its meta-key blocklist fails to account for subsite-prefixed capability and user level keys (e.g., 'wp_2_capabilities'). An authenticated attacker with Subscriber-level access can exploit this by submitting a crafted profile update to grant themselves Administrator privileges on a subsite, provided a site administrator has previously exposed these fields via a CSV import.","\u002F\u002F classes\u002Fmultisite.php\n\n\tfunction restricted_fields( $acui_restricted_fields ){\n\t\treturn array_merge( $acui_restricted_fields, array( 'blogs' ) );\n\t}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fimport-users-from-csv-with-meta\u002F2.0.8\u002Fclasses\u002Fimport.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fimport-users-from-csv-with-meta\u002F2.0.9\u002Fclasses\u002Fimport.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fimport-users-from-csv-with-meta\u002F2.0.8\u002Fclasses\u002Fimport.php\t2026-04-24 21:00:36.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fimport-users-from-csv-with-meta\u002F2.0.9\u002Fclasses\u002Fimport.php\t2026-04-26 07:50:22.000000000 +0000\n@@ -764,9 +764,12 @@\n         \u002F\u002F On first step, we might need to handle the upload if it's there\n         if( $step == 1 && empty( $file ) ){\n             if( !empty( $_FILES['uploadfile']['tmp_name'] ) ){\n-                \u002F\u002F Move uploaded file to a more permanent temporary location because tmp_name is deleted after request\n-                $upload_dir = wp_upload_dir();\n                 $original_ext = strtolower( pathinfo( $_FILES['uploadfile']['name'], PATHINFO_EXTENSION ) );\n+                $allowed_extensions = apply_filters( 'acui_allowed_upload_extensions', array( 'csv' ) );\n+                if( !in_array( $original_ext, $allowed_extensions, true ) ){\n+                    wp_send_json_error( array( 'message' => __( 'Invalid file type.', 'import-users-from-csv-with-meta' ) ) );\n+                }\n+                $upload_dir = wp_upload_dir();\n                 $file = $upload_dir['basedir'] . '\u002Facui-import-' . uniqid() . '.' . $original_ext;\n                 move_uploaded_file( $_FILES['uploadfile']['tmp_name'], $file );\n             }\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fimport-users-from-csv-with-meta\u002F2.0.8\u002Fclasses\u002Fmultisite.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fimport-users-from-csv-with-meta\u002F2.0.9\u002Fclasses\u002Fmultisite.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fimport-users-from-csv-with-meta\u002F2.0.8\u002Fclasses\u002Fmultisite.php\t2026-03-15 23:08:34.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fimport-users-from-csv-with-meta\u002F2.0.9\u002Fclasses\u002Fmultisite.php\t2026-04-26 07:50:22.000000000 +0000\n@@ -18,6 +18,12 @@\n \t}\n \n \tfunction restricted_fields( $acui_restricted_fields ){\n+\t\tglobal $wpdb;\n+\t\tforeach ( $this->sites as $site ) {\n+\t\t\t$prefix = $wpdb->get_blog_prefix( $site->blog_id );\n+\t\t\t$acui_restricted_fields[] = $prefix . 'capabilities';\n+\t\t\t$acui_restricted_fields[] = $prefix . 'user_level';\n+\t\t}\n \t\treturn array_merge( $acui_restricted_fields, array( 'blogs' ) );\n \t}","The exploit targets WordPress Multisite installations where an administrator has previously imported a CSV file containing subsite-specific capability columns (e.g., 'wp_2_capabilities') and enabled the 'Show fields in profile?' option. An attacker with Subscriber-level access logs into the site and navigates to the standard profile update page (\u002Fwp-admin\u002Fprofile.php). After extracting the valid '_wpnonce' from the page, the attacker submits a POST request to the same endpoint. The payload includes the subsite's capability key (e.g., 'wp_2_capabilities') set to a serialized administrator role array and the 'wp_2_user_level' key set to '10'. Because the plugin's blocklist does not recognize site-prefixed capability keys, it allows the attacker to write directly to their user meta, granting them administrative privileges on the specified subsite.","gemini-3-flash-preview","2026-05-04 17:17:14","2026-05-04 17:17:37",{"type":38,"vulnerable_version":39,"fixed_version":11,"vulnerable_browse":40,"vulnerable_zip":41,"fixed_browse":42,"fixed_zip":43,"all_tags":44},"plugin","2.0.8","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fimport-users-from-csv-with-meta\u002Ftags\u002F2.0.8","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fimport-users-from-csv-with-meta.2.0.8.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fimport-users-from-csv-with-meta\u002Ftags\u002F2.0.9","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fimport-users-from-csv-with-meta.2.0.9.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fimport-users-from-csv-with-meta\u002Ftags"]