[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f-mhRXZ4kNo59_oiOSu79hMjnUJnIk3gksfueNj2FTm8":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":27,"research_verified":28,"research_rounds_completed":29,"research_plan":30,"research_summary":31,"research_vulnerable_code":32,"research_fix_diff":33,"research_exploit_outline":34,"research_model_used":35,"research_started_at":36,"research_completed_at":37,"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":28,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":28,"source_links":38},"CVE-2026-40773","rtmedia-for-wordpress-buddypress-and-bbpress-missing-authorization","rtMedia for WordPress, BuddyPress and bbPress \u003C= 4.7.9 - Missing Authorization","The rtMedia for WordPress, BuddyPress and bbPress plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 4.7.9. This makes it possible for authenticated attackers, with subscriber-level access and above, to perform an unauthorized action.","buddypress-media",null,"\u003C=4.7.9","4.7.10","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-04-21 00:00:00","2026-04-30 14:41:33",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fcacd9237-a330-4927-ac53-ee86b9ac8289?source=api-prod",10,[22,23,24,25,26],".github\u002Fworkflows\u002Fplaywright.yml","app\u002Fmain\u002Fcontrollers\u002Ftemplate\u002Frtmedia-ajax-actions.php","changelog.txt","index.php","readme.txt","researched",false,3,"# Exploitation Research Plan: CVE-2026-40773 (rtMedia Missing Authorization)\n\n## 1. Vulnerability Summary\nThe **rtMedia** plugin for WordPress is vulnerable to **Missing Authorization** in its AJAX media deletion handler. The function `rtmedia_delete_uploaded_media()` in `app\u002Fmain\u002Fcontrollers\u002Ftemplate\u002Frtmedia-ajax-actions.php` verifies a WordPress nonce but fails to check:\n1.  If the current user has the capability to delete media (e.g., `delete_posts`).\n2.  If the `media_id` provided in the request actually belongs to the current user (Insecure Direct Object Reference - IDOR).\n\nAs a result, any authenticated user (Subscriber and above) can delete any media uploaded via rtMedia (photos, videos, music) by providing their own valid nonce and the target `media_id`.\n\n## 2. Attack Vector Analysis\n-   **Endpoint**: `\u002Fwp-admin\u002Fadmin-ajax.php`\n-   **Action**: `delete_uploaded_media` (hooked via `wp_ajax_delete_uploaded_media`)\n-   **HTTP Method**: `POST`\n-   **Parameters**:\n    -   `action`: `delete_uploaded_media`\n    -   `media_id`: The ID of the rtMedia entry to delete.\n    -   `nonce`: A nonce valid for the action string `'rtmedia_' . get_current_user_id()`.\n-   **Authentication**: Required (Subscriber level or higher).\n-   **Preconditions**: The attacker must be able to obtain a valid nonce for themselves, which the plugin provides on pages where the media gallery is loaded.\n\n## 3. Code Flow\n1.  **Entry Point**: The user sends a POST request to `admin-ajax.php` with `action=delete_uploaded_media`.\n2.  **Hook Registration**: `app\u002Fmain\u002Fcontrollers\u002Ftemplate\u002Frtmedia-ajax-actions.php` registers the handler:\n    ```php\n    add_action( 'wp_ajax_delete_uploaded_media', 'rtmedia_delete_uploaded_media' );\n    ```\n3.  **Parameter Extraction**: Inside `rtmedia_delete_uploaded_media()`:\n    -   `$nonce` is taken from `$_POST['nonce']`.\n    -   `$media_id` is taken from `$_POST['media_id']`.\n4.  **Nonce Verification**:\n    ```php\n    if ( wp_verify_nonce( $nonce, 'rtmedia_' . get_current_user_id() ) ) {\n    ```\n    This verifies that the nonce was generated for the *current* user. It does *not* verify that the user has permission to delete the specific `$media_id`.\n5.  **Vulnerable Sink**:\n    ```php\n    $rtmedia_media = new RTMediaMedia();\n    $rtmedia_media->delete( $media_id );\n    ```\n    The `delete()` method is called directly with the user-supplied `media_id`, leading to unauthorized deletion of media belonging to other users.\n\n## 4. Nonce Acquisition Strategy\nThe nonce is generated per-user using the action string `'rtmedia_' . get_current_user_id()`. This nonce is localized and passed to the frontend for the plugin's legitimate delete functionality.\n\n1.  **Identify Trigger**: rtMedia enqueues its scripts on pages containing the `[rtmedia_gallery]` shortcode or on BuddyPress profile media tabs.\n2.  **Shortcode Creation**: Create a public page with the gallery shortcode to ensure the scripts load for the Subscriber.\n    -   `wp post create --post_type=page --post_status=publish --post_title=\"Media\" --post_content=\"[rtmedia_gallery]\"`\n3.  **Extraction**: Navigate to this page as the Subscriber and use `browser_eval` to extract the nonce from the `rtmedia_ajax_params` global object.\n    -   **JS Variable**: `window.rtmedia_ajax_params`\n    -   **Nonce Key**: `nonce`\n    -   **Command**: `browser_eval(\"window.rtmedia_ajax_params ? window.rtmedia_ajax_params.nonce : 'not_found'\")`\n\n## 5. Exploitation Strategy\n\n### Step 1: Target Identification\nAs an Admin, upload a media file and identify its rtMedia ID. rtMedia uses its own database table (`wp_rt_rtm_media`).\n```bash\n# Get the ID of the latest uploaded rtMedia entry\nwp db query \"SELECT id FROM wp_rt_rtm_media ORDER BY id DESC LIMIT 1;\"\n```\n\n### Step 2: Nonce Retrieval\nLog in as the Subscriber, navigate to the media page, and extract the nonce using the strategy in Section 4.\n\n### Step 3: Unauthorized Deletion Request\nUse the `http_request` tool to send the malicious payload.\n\n-   **URL**: `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n-   **Headers**: `Content-Type: application\u002Fx-www-form-urlencoded`\n-   **Body**:\n    ```\n    action=delete_uploaded_media&nonce=[SUBSCRIBER_NONCE]&media_id=[TARGET_MEDIA_ID]\n    ```\n\n### Step 4: Verification\nConfirm the deletion using WP-CLI.\n\n## 6. Test Data Setup\n1.  **Users**:\n    -   Admin: `admin` \u002F `password`\n    -   Subscriber: `attacker` \u002F `password`\n2.  **Content**:\n    -   Create a page for nonce extraction: `[rtmedia_gallery]`.\n    -   The Admin must upload at least one image via the rtMedia interface (e.g., via the BuddyPress profile or a gallery page) so there is a `media_id` to target.\n    -   *Note*: Ensure BuddyPress is active or the rtMedia \"Allow upload from WordPress author page\" setting is enabled to facilitate the upload.\n\n## 7. Expected Results\n-   **AJAX Response**:\n    ```json\n    {\n        \"success\": true,\n        \"data\": {\n            \"code\": \"rtmedia-media-deleted\",\n            ...\n        }\n    }\n    ```\n-   **Database State**: The record with `id = [TARGET_MEDIA_ID]` should be removed from the `wp_rt_rtm_media` table.\n-   **Filesystem State**: The associated attachment file in `wp-content\u002Fuploads\u002F` (if it was the primary media) should be deleted or detached.\n\n## 8. Verification Steps\n1.  **Check Table**:\n    ```bash\n    wp db query \"SELECT count(*) FROM wp_rt_rtm_media WHERE id = [TARGET_MEDIA_ID];\"\n    ```\n    The count should be `0`.\n2.  **Check Attachment**:\n    Check if the WordPress attachment associated with that media ID (if any) still exists.\n\n## 9. Alternative Approaches\nIf `rtmedia_ajax_params` is not found, check for:\n-   `rtMedia_plupload_config.multipart_params.nonce`\n-   Searching the entire page source for the string `rtmedia_` followed by the current user ID to see how the nonce is assigned to HTML attributes (e.g., `data-nonce` on a delete button).\n-   If the `rtmedia_` user ID nonce is not present, check if the plugin accidentally falls back to a default nonce for action `-1` in certain configurations.","The rtMedia plugin for WordPress is vulnerable to unauthorized media deletion due to a missing authorization check and an insecure direct object reference (IDOR) in its AJAX handler. This allows authenticated attackers with subscriber-level permissions to delete any media uploaded through the plugin by supplying a valid nonce tied to their own user ID and a target media ID.","\u002F\u002F app\u002Fmain\u002Fcontrollers\u002Ftemplate\u002Frtmedia-ajax-actions.php line 12\nfunction rtmedia_delete_uploaded_media() {\n\n\t$action   = sanitize_text_field( filter_input( INPUT_POST, 'action', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) );\n\t$nonce    = sanitize_text_field( filter_input( INPUT_POST, 'nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) );\n\t$media_id = filter_input( INPUT_POST, 'media_id', FILTER_SANITIZE_NUMBER_INT );\n\n\tif ( ! empty( $action ) && 'delete_uploaded_media' === $action && ! empty( $media_id ) ) {\n\t\tif ( wp_verify_nonce( $nonce, 'rtmedia_' . get_current_user_id() ) ) {\n\t\t\t$remaining_album     = 0;\n\t\t\t$remaining_photos    = 0;\n\t\t\t$remaining_music     = 0;\n\t\t\t$remaining_videos    = 0;\n\t\t\t$remaining_all_media = 0;\n\t\t\t$rtmedia_media       = new RTMediaMedia();\n\t\t\t$rtmedia_media->delete( $media_id );","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fbuddypress-media\u002F4.7.9\u002Fapp\u002Fmain\u002Fcontrollers\u002Ftemplate\u002Frtmedia-ajax-actions.php\t2025-10-30 08:47:14.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fbuddypress-media\u002F4.7.10\u002Fapp\u002Fmain\u002Fcontrollers\u002Ftemplate\u002Frtmedia-ajax-actions.php\t2026-04-07 09:50:32.000000000 +0000\n@@ -7,7 +7,7 @@\n \n \u002F**\n  * Delete uploaded media.\n- * Modified 10-02-2019 by Adarsh Verma \u003Cadarsh.verma@rtcamp.com>\n+ * Patched to include Ownership and Authorization checks.\n  *\u002F\n function rtmedia_delete_uploaded_media() {\n \n@@ -17,6 +17,47 @@\n \n \tif ( ! empty( $action ) && 'delete_uploaded_media' === $action && ! empty( $media_id ) ) {\n \t\tif ( wp_verify_nonce( $nonce, 'rtmedia_' . get_current_user_id() ) ) {\n+\n+\t\t\t$model = new RTMediaModel();\n+\t\t\t$media = $model->get( array( 'id' => $media_id ) );\n+\n+\t\t\t\u002F\u002F Check if media exists\n+\t\t\tif ( empty( $media ) || ! isset( $media[0] ) ) {\n+\t\t\t\twp_send_json_error(\n+\t\t\t\t\tarray(\n+\t\t\t\t\t\t'code'    => 'rtmedia-media-not-found',\n+\t\t\t\t\t\t'message' => esc_html__( 'Media not found.', 'buddypress-media' ),\n+\t\t\t\t\t)\n+\t\t\t\t);\n+\t\t\t\twp_die();\n+\t\t\t}\n+\n+\t\t\t$current_user_id = get_current_user_id();\n+\t\t\t$media_author    = (int) $media[0]->media_author;\n+\n+\t\t\t\u002F\u002F 1. Is the user the owner of the media?\n+\t\t\t$is_owner = ( $current_user_id === $media_author );\n+\n+\t\t\t\u002F\u002F 2. Is the user a site administrator?\n+\t\t\t$is_admin = current_user_can( 'manage_options' ) || current_user_can( 'delete_others_posts' );\n+\n+\t\t\t\u002F\u002F 3. Is the user a BuddyPress Group Admin? (if the media belongs to a BP group)\n+\t\t\t$is_group_admin = false;\n+\t\t\tif ( ! empty( $media[0]->context ) && 'group' === $media[0]->context && function_exists( 'groups_is_user_admin' ) ) {\n+\t\t\t\t$is_group_admin = groups_is_user_admin( $current_user_id, $media[0]->context_id );\n+\t\t\t}\n+\n+\t\t\t\u002F\u002F If none of the above are true, block the deletion\n+\t\t\tif ( ! $is_owner && ! $is_admin && ! $is_group_admin ) {\n+\t\t\t\twp_send_json_error(\n+\t\t\t\t\tarray(\n+\t\t\t\t\t\t'code'    => 'rtmedia-unauthorized',\n+\t\t\t\t\t\t'message' => esc_html__( 'You do not have permission to delete this media.', 'buddypress-media' ),\n+\t\t\t\t\t)\n+\t\t\t\t);\n+\t\t\t\twp_die();\n+\t\t\t}\n+\n \t\t\t$remaining_album     = 0;\n \t\t\t$remaining_photos    = 0;\n \t\t\t$remaining_music     = 0;\n@@ -29,7 +70,6 @@\n \t\t\tif ( class_exists( 'RTMediaNav' ) ) {\n \t\t\t\tglobal $bp;\n \t\t\t\t$rtmedia_nav_obj = new RTMediaNav();\n-\t\t\t\t$model           = new RTMediaModel();\n \t\t\t\t$other_count     = 0;\n \n \t\t\t\tif ( function_exists( 'bp_is_group' ) && bp_is_group() ) {","1. Authentication: Log in to the WordPress site as a Subscriber-level user.\n2. Nonce Acquisition: Navigate to any page where rtMedia is active (e.g., a page with the `[rtmedia_gallery]` shortcode). Extract the security nonce from the global JavaScript object `rtmedia_ajax_params.nonce`.\n3. Target Identification: Identify the `media_id` of a target media file (uploaded by an administrator or another user) within the `wp_rt_rtm_media` table or by inspecting gallery links.\n4. Unauthorized Request: Send a POST request to `\u002Fwp-admin\u002Fadmin-ajax.php` with the following body:\n   - `action`: `delete_uploaded_media` \n   - `nonce`: [Your extracted nonce]\n   - `media_id`: [The target ID]\n5. Verification: The plugin verifies the nonce against the attacker's user ID but performs no ownership check, resulting in the deletion of the target media file and its database record.","gemini-3-flash-preview","2026-05-04 19:17:16","2026-05-04 19:17:52",{"type":39,"vulnerable_version":40,"fixed_version":11,"vulnerable_browse":41,"vulnerable_zip":42,"fixed_browse":43,"fixed_zip":44,"all_tags":45},"plugin","4.7.9","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbuddypress-media\u002Ftags\u002F4.7.9","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fbuddypress-media.4.7.9.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbuddypress-media\u002Ftags\u002F4.7.10","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fbuddypress-media.4.7.10.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbuddypress-media\u002Ftags"]