[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fjuHZ-ym_0nAJfgo0xI0rw4ulJa9JRHqadGfSn1XK7uM":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":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"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":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-4654","awesome-support-authenticated-subscriber-insecure-direct-object-reference-to-unauthorized-ticket-reply-access-via-ticket","Awesome Support \u003C= 6.3.7 - Authenticated (Subscriber+) Insecure Direct Object Reference to Unauthorized Ticket Reply Access via 'ticket_id' Parameter","The Awesome Support – WordPress HelpDesk & Support Plugin plugin for WordPress is vulnerable to Insecure Direct Object Reference in versions up to, and including, 6.3.7. This is due to the wpas_get_ticket_replies_ajax() function failing to verify whether the authenticated user has permission to view the specific ticket being requested. This makes it possible for authenticated attackers, with subscriber-level access and above, to access sensitive information from all support tickets in the system by manipulating the ticket_id parameter.","awesome-support",null,"\u003C=6.3.7","6.3.8","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:L\u002FI:N\u002FA:N","Authorization Bypass Through User-Controlled Key","2026-04-07 00:00:00","2026-04-08 07:43:02",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F9f9015fa-b3f0-4312-8acd-02b715e26f33?source=api-prod",1,[22,23,24,25,26,27,28,29],"assets\u002Fadmin\u002Fjs\u002Fadmin-print-ticket.js","awesome-support.php","includes\u002Fadmin\u002Fmetaboxes\u002Fticket-additional-parties.php","includes\u002Fadmin\u002Fviews\u002Fabout-tab-change-log.php","includes\u002Fadmin\u002Fviews\u002Fprint-ticket.php","includes\u002Ffile-uploader\u002Fclass-file-uploader.php","includes\u002Ffunctions-general.php","includes\u002Ffunctions-post.php","researched",false,3,"# Exploitation Research Plan: CVE-2026-4654 - Awesome Support IDOR\n\n## 1. Vulnerability Summary\nThe **Awesome Support** plugin (\u003C= 6.3.7) is vulnerable to an **Insecure Direct Object Reference (IDOR)**. The vulnerability exists in the AJAX handler responsible for fetching ticket replies (identified in the description as `wpas_get_ticket_replies_ajax()` and appearing in source as part of the `wpas_get_ticket_for_print` action). \n\nThe application fails to verify if the currently authenticated user (even with a low-privilege `Subscriber` role) has the authorization to view the ticket identified by the `ticket_id` (or `id`) parameter. Consequently, any logged-in user can access the contents and private replies\u002Fnotes of any support ticket in the database by simply guessing or incrementing the ID.\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Action:** `wpas_get_ticket_for_print` (as seen in `assets\u002Fadmin\u002Fjs\u002Fadmin-print-ticket.js`) or `wpas_get_ticket_replies_ajax` (as per the CVE description).\n*   **HTTP Method:** `POST`\n*   **Vulnerable Parameter:** `id` (or `ticket_id`)\n*   **Authentication Required:** Authenticated (`Subscriber` role or higher).\n*   **Preconditions:** The attacker must obtain a valid WordPress AJAX nonce, typically localized as `WPAS_Print.nonce`.\n\n## 3. Code Flow\n1.  **Entry Point:** An authenticated user sends a `POST` request to `admin-ajax.php` with the action `wpas_get_ticket_for_print`.\n2.  **Nonce Verification:** The handler calls `check_ajax_referer()` or `wp_verify_nonce()` using the provided `nonce` parameter and the action string (likely `'wpas-print-ticket'`).\n3.  **Missing Authorization Sink:** The backend function (likely in an admin controller) retrieves the ticket object using `get_post( $id )`. \n4.  **Information Disclosure:** The code proceeds to fetch all related posts with types `ticket_reply`, `ticket_note`, and `ticket_history` without checking if the `post_author` of the ticket matches the current user ID or if the user has `edit_others_tickets` capabilities.\n5.  **Output:** The content is rendered using the template `includes\u002Fadmin\u002Fviews\u002Fprint-ticket.php`, which explicitly includes private notes:\n    ```php\n    \u002F\u002F From includes\u002Fadmin\u002Fviews\u002Fprint-ticket.php\n    \u003Ctable class=\"\u003C?php echo ( $reply->post_type == 'ticket_note' ) ? 'wpas-print-ticket-notes' : 'wpas-print-ticket-reply'; ?>\">\n    ...\n    \u003C?php if ( $reply->post_type == 'ticket_note' ) printf( ' - \u003Cstrong>%s\u003C\u002Fstrong>', esc_html__( 'Private note', 'awesome-support' ) ); ?>\n    ```\n\n## 4. Nonce Acquisition Strategy\nThe nonce is localized in the WordPress admin dashboard for users who have access to ticket-related pages. Even a Subscriber may have access to the backend if Awesome Support is configured to use the admin area for the \"My Tickets\" view.\n\n1.  **Identify Script Localization:** The script `assets\u002Fadmin\u002Fjs\u002Fadmin-print-ticket.js` is enqueued with the localization object `WPAS_Print`.\n2.  **Navigation:** Use `browser_navigate` to go to the ticket list or the main dashboard: `\u002Fwp-admin\u002Fedit.php?post_type=ticket`.\n3.  **Extraction:**\n    ```javascript\n    \u002F\u002F Use browser_eval to extract the nonce\n    const nonce = window.WPAS_Print?.nonce;\n    return nonce;\n    ```\n4.  **Alternative:** If the Subscriber is barred from the backend, check if `WPAS_Print` is localized on the frontend \"My Tickets\" page (shortcode `[tickets]`).\n\n## 5. Exploitation Strategy\n### Step 1: Discover Target ID\nIdentify a sensitive ticket ID (e.g., Ticket #1, created by an Admin containing credentials).\n\n### Step 2: Perform IDOR Request\nSend a crafted request to the AJAX endpoint to retrieve the full content of the target ticket, including private notes.\n\n**Request Template:**\n*   **URL:** `http:\u002F\u002F\u003Ctarget>\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Method:** `POST`\n*   **Content-Type:** `application\u002Fx-www-form-urlencoded`\n*   **Body:**\n    ```text\n    action=wpas_get_ticket_for_print&id=\u003CTARGET_TICKET_ID>&nonce=\u003CSTOLEN_NONCE>\n    ```\n\n## 6. Test Data Setup\n1.  **Admin User:** Create a \"Sensitive Ticket\" (Post Type: `ticket`).\n    *   Title: \"Server Migration Credentials\"\n    *   Content: \"The root password is 'P4ssw0rd!'\"\n2.  **Private Note:** Add a private note to this ticket (Post Type: `ticket_note`).\n    *   Content: \"Also, the database secret is 'db_admin_123'\"\n3.  **Subscriber User:** Create a user `attacker_sub` with the `Subscriber` role.\n4.  **Attacker Ticket:** (Optional) Create one ticket for `attacker_sub` to ensure they have access to the \"My Tickets\" page where the nonce is likely localized.\n\n## 7. Expected Results\n*   The server returns an `HTTP 200 OK` response.\n*   The response body contains an HTML string (the rendered `print-ticket.php` view).\n*   The HTML content reveals the \"Sensitive Ticket\" title, the root password from the content, and the database secret from the `ticket_note` section, which should have been hidden from the Subscriber.\n\n## 8. Verification Steps\n1.  **Response Inspection:** Search the AJAX response for the string `\"Private note\"`.\n2.  **Data Comparison:** Verify the disclosed password in the response matches the one created in the Test Data Setup.\n3.  **CLI Confirmation:**\n    ```bash\n    # Confirm the ticket author is NOT the Subscriber\n    wp post get \u003CTARGET_ID> --field=post_author\n    # Compare with Subscriber ID\n    wp user get attacker_sub --field=ID\n    ```\n\n## 9. Alternative Approaches\nIf `wpas_get_ticket_for_print` is strictly protected by a capability check, test the alternative action mentioned in the CVE description:\n*   **Action:** `wpas_get_ticket_replies_ajax`\n*   **Parameter:** `ticket_id`\n*   **Expected Behavior:** This endpoint likely returns a JSON blob of replies. If it lacks the `current_user_can` or `post_author` check, it will leak the same sensitive info.\n\nIf the nonce is missing, check if `wpas_get_ticket_replies_ajax` was registered using `wp_ajax_nopriv_` (unlikely for a Subscriber+ vuln, but worth checking).","The Awesome Support plugin for WordPress is vulnerable to an Insecure Direct Object Reference (IDOR) in versions up to 6.3.7. The AJAX function `wpas_get_ticket_replies_ajax` fails to verify if the requester is authorized to view the specific ticket identified by the `ticket_id` parameter, allowing low-privileged authenticated users (Subscriber+) to access sensitive ticket data, including private notes.","\u002F\u002F includes\u002Ffunctions-post.php line 1822\n\t$ticket_id = absint( $_POST['ticket_id'] );\t\n\n\t\u002F\u002FCheck permission for capability of current user\n\tif ( ! current_user_can( 'reply_ticket' ) ) {\n\t\twp_send_json_error( array('message' => __('Unauthorized action. You do not have permission to load TinyMCE via Ajax request to edit a reply.', 'awesome-support') ), 403);\t\t\n    }\t\n\t\t\n\tif( !check_ajax_referer( 'wpas_loads_replies', 'ticket_replies_nonce', false ) ) {\t\t\n\t\twp_send_json_error( array( 'message' => \"You don't have access to perform this action\" ) );\n\t\tdie();\n\t}","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fawesome-support\u002F6.3.7\u002Fincludes\u002Ffunctions-post.php\t2025-09-22 18:48:12.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fawesome-support\u002F6.3.8\u002Fincludes\u002Ffunctions-post.php\t2026-04-02 16:18:42.000000000 +0000\n@@ -1822,14 +1822,27 @@\n \t\n \t$ticket_id = absint( $_POST['ticket_id'] );\t\n \n-\t\u002F\u002FCheck permission for capability of current user\n-\tif ( ! current_user_can( 'reply_ticket' ) ) {\n-\t\twp_send_json_error( array('message' => __('Unauthorized action. You do not have permission to load TinyMCE via Ajax request to edit a reply.', 'awesome-support') ), 403);\t\t\n-    }\t\n-\t\t\n-\tif( !check_ajax_referer( 'wpas_loads_replies', 'ticket_replies_nonce', false ) ) {\t\t\n-\t\twp_send_json_error( array( 'message' => \"You don't have access to perform this action\" ) );\n-\t\tdie();\n+\t\u002F* Check if the ticket is public (wpas_pbtk_flag) - only allow public access if the Public Tickets add-on is active *\u002F\n+\t$pbtk_flag = get_post_meta( $ticket_id , '_wpas_pbtk_flag', true );\t\t\n+\tif ( class_exists( 'AS_Publictickets_Loader' ) && 'public' === $pbtk_flag ) {\n+\t\t$can_view = true;\n+\t}\n+\telse\n+\t{\n+\t\t\u002F\u002FCheck permission for VIEW capability of current user\n+\t\tif ( ! wpas_can_view_ticket( $ticket_id ) ) {\n+\t\t\twp_send_json_error( array('message' => esc_html__('You are not allowed to view this ticket.', 'awesome-support') ), 403);\n+\t\t\tdie();\n+\t\t}\n+\t\t\u002F\u002FCheck permission for REPLY capability of current user\n+\t\tif ( ! current_user_can( 'reply_ticket' ) ) {\n+\t\t\twp_send_json_error( array('message' => esc_html__('Unauthorized action. You do not have permission to load TinyMCE via Ajax request to edit a reply.', 'awesome-support') ), 403);\t\t\n+\t    }\t\n+\t\t\u002F\u002FCheck permission for Valid nonce of current user\n+\t\tif( !check_ajax_referer( 'wpas_loads_replies', 'ticket_replies_nonce', false ) ) {\t\t\n+\t\t\twp_send_json_error( array( 'message' =>  esc_html__(\"You don't have access to perform this action\", 'awesome-support') ), 403 );\n+\t\t\tdie();\n+\t\t}\n \t}","1. Authenticate as a user with at least Subscriber privileges.\n2. Locate a valid AJAX nonce for the 'wpas_loads_replies' action (typically found localized in the admin dashboard scripts, for instance under the 'WPAS_Print' or similar global JS objects).\n3. Identify the numeric ID of a target support ticket belonging to another user.\n4. Send a POST request to `\u002Fwp-admin\u002Fadmin-ajax.php` with the following parameters: `action=wpas_get_ticket_replies_ajax`, `ticket_id=\u003CTARGET_ID>`, and `ticket_replies_nonce=\u003CVALID_NONCE>`.\n5. The server will respond with a JSON array containing the full reply history and private notes of the target ticket, bypassing intended ownership restrictions.","gemini-3-flash-preview","2026-04-17 21:12:59","2026-04-17 21:13:26",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","6.3.7","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fawesome-support\u002Ftags\u002F6.3.7","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fawesome-support.6.3.7.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fawesome-support\u002Ftags\u002F6.3.8","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fawesome-support.6.3.8.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fawesome-support\u002Ftags"]