CVE-2026-25329

Quiz and Survey Master (QSM) – Easy Quiz and Survey Maker <= 10.3.4 - Missing Authorization

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
10.3.5
Patched in
89d
Time to patch

Description

The Quiz and Survey Master (QSM) – Easy Quiz and Survey Maker plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 10.3.4. This makes it possible for authenticated attackers, with Subscriber-level access and above, to perform an unauthorized action.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=10.3.4
PublishedFebruary 5, 2026
Last updatedMay 4, 2026
Affected pluginquiz-master-next

What Changed in the Fix

Changes introduced in v10.3.5

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan targets a missing authorization vulnerability in **Quiz and Survey Master (QSM) <= 10.3.4**. Specifically, it exploits the `enable_multiple_categories` AJAX action, which lacks a capability check and incorrectly relies on the generic `wp_rest` nonce, making it accessible to any au…

Show full research plan

This research plan targets a missing authorization vulnerability in Quiz and Survey Master (QSM) <= 10.3.4. Specifically, it exploits the enable_multiple_categories AJAX action, which lacks a capability check and incorrectly relies on the generic wp_rest nonce, making it accessible to any authenticated user, including those with Subscriber roles.

1. Vulnerability Summary

  • Vulnerability: Missing Authorization.
  • Vulnerable Function: QSM_Migrate::enable_multiple_categories.
  • File Path: php/classes/class-qsm-migrate.php.
  • Root Cause: The function verifies a nonce (wp_rest) and checks is_admin(). However, is_admin() only checks if the current request is for an admin screen (which includes admin-ajax.php) and is not a capability check. No current_user_can() check is performed, allowing any authenticated user to modify plugin settings or trigger database operations.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php.
  • Action: enable_multiple_categories.
  • Method: POST.
  • Authentication: Required (Subscriber or higher).
  • Required Parameter: nonce (must be a valid wp_rest nonce).
  • Payload Parameter: value=cancel (to modify the qsm_multiple_category_enabled option).

3. Code Flow

  1. Entry Point: wp-admin/admin-ajax.php receives a request with action=enable_multiple_categories.
  2. Hook Registration: QSM_Migrate::__construct (in php/classes/class-qsm-migrate.php) registers the action:
    add_action( 'wp_ajax_enable_multiple_categories', array( $this, 'enable_multiple_categories' ) );.
  3. Vulnerable Function Call: enable_multiple_categories() is executed.
  4. Insufficient Verification:
    • It checks $_POST['nonce'] against 'wp_rest'. Any logged-in user can obtain a wp_rest nonce as it is used by the standard WordPress REST API.
    • It does not check for a specific capability (e.g., manage_options).
  5. Sink: If $_POST['value'] is 'cancel', it executes:
    update_option( 'qsm_multiple_category_enabled', 'cancelled' );.

4. Nonce Acquisition Strategy

The endpoint requires a wp_rest nonce. WordPress typically localizes this for the REST API in the admin dashboard.

  1. Identify Trigger: The wp_rest nonce is standard for any user logged into the WordPress dashboard.
  2. Navigation: Navigate to a standard admin page accessible to Subscribers, such as wp-admin/profile.php.
  3. Extraction: Use browser_eval to extract the nonce from the wpApiSettings global object or the wp-api-js-extra script block.
    • JS Command: window.wpApiSettings?.nonce or window._wpnonce.

5. Exploitation Strategy

  1. Authentication: Log in as a Subscriber.
  2. Nonce Retrieval: Navigate to /wp-admin/profile.php and execute browser_eval("window.wpApiSettings.nonce") to get the wp_rest nonce.
  3. Execute Payload: Send a POST request to /wp-admin/admin-ajax.php using the http_request tool.
    • Headers: Content-Type: application/x-www-form-urlencoded.
    • Body: action=enable_multiple_categories&nonce=[EXTRACTED_NONCE]&value=cancel.
  4. Alternative (High Impact): If a qmn_failed_submission nonce is discovered (check localized scripts in wp-admin/admin.php?page=mlw_quizmaster_results), the same logic can be applied to qsm_action_failed_submission_table to trash arbitrary posts.

6. Test Data Setup

  1. Plugin Configuration: Ensure the plugin is active and configured.
  2. Initial State: Ensure the option qsm_multiple_category_enabled is NOT set to 'cancelled'.
    • wp option update qsm_multiple_category_enabled 0
  3. User Creation: Create a subscriber user:
    • wp user create attacker attacker@example.com --role=subscriber --user_pass=password

7. Expected Results

  • The AJAX request should return a JSON success response: {"success":true}.
  • The WordPress option qsm_multiple_category_enabled will be updated to the string 'cancelled'.

8. Verification Steps

  1. WP-CLI Check: Verify the option value after the exploit.
    • wp option get qsm_multiple_category_enabled
    • Expected Output: cancelled.
  2. Audit Logs: If audit logging is active, check for the unauthorized change.

9. Alternative Approaches

If the wp_rest nonce is not easily found:

  • REST API Discovery: Check /wp-json/ headers for a X-WP-Nonce.
  • Other vulnerable endpoints:
    • qsm_check_fix_db (action) using nonce qmn_check_db.
    • qsm_action_failed_submission_table (action) using nonce qmn_failed_submission.
      These also lack capability checks in class-qmn-quiz-manager.php. If a Subscriber can access a page where these nonces are localized (via wp_localize_script), they can exploit these endpoints to trigger SQL (ALTER TABLE) or trash posts.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.