1. Vulnerability Background
What is this vulnerability?
- CVE-2025-9637 affects the WordPress plugin Quiz and Survey Master (QSM) – Easy Quiz and Survey Maker in versions up to and including 10.3.1.
- The vulnerability is caused by missing authorization and status checks in
php/classes/class-qmn-quiz-manager.phpfor quiz-related AJAX and submission handlers. - It allows unauthenticated users to access quiz details for unpublished, private, or password-protected quizzes and to submit file responses to those quizzes.
Why is it critical/important?
- Unauthorized access to unpublished or protected content bypasses intended access controls and leaks sensitive quiz configuration and question data.
- The ability to submit file responses from protected quizzes opens a second attack surface, enabling unauthenticated file uploads and potentially malicious payload delivery.
- The issue combines information disclosure with an unauthorized upload capability, increasing the attack impact on affected WordPress sites.
What systems/versions are affected?
- WordPress sites running the QSM plugin version 10.3.1 or earlier.
- Any installation where the plugin is active and exposes the affected AJAX endpoints and quiz submission endpoints.
2. Technical Details
Root cause analysis
- The core issue is missing authorization checks on plugin functions exposed via WordPress AJAX endpoints.
wp_ajax_nopriv_qsm_get_quiz_to_reloadregistered an unauthenticated endpoint, meaning anyone could call the quiz reload routine.- The plugin also failed to validate quiz post protection for submissions, allowing responses to protected quizzes without requiring the quiz password.
- An additional fix in the patch enforces strict type checking in
in_array()calls, reducing the chance of malicious type-coercion bypasses.
Attack vector and exploitation conditions
- An attacker only needs network access to the WordPress site and knowledge of QSM AJAX action names or the quiz submission endpoint.
- Unauthenticated requests to
admin-ajax.phpwith actions such asqsm_get_quiz_to_reloadcould retrieve quiz details. - File upload endpoints tied to quiz response submission could accept files from unauthenticated sources when a quiz was unpublished, private, or password-protected.
- Exploitation requires no authenticated session if the vulnerable endpoints remain exposed.
Security implications
- Data exposure: unpublished and private quiz configuration, questions, and potentially answer payloads are disclosed to attackers.
- Access control bypass: password-protected quizzes are effectively bypassed for submission actions.
- File upload risk: unauthenticated file responses can be used to introduce arbitrary content, which, depending on the upload handling, may lead to further compromise.
- Trust boundary violation: quiz access controls that should be enforced by WordPress are undermined by plugin logic.
3. Patch Analysis
What code changes were made?
- The patch removed the
wp_ajax_nopriv_qsm_get_quiz_to_reloadregistration fromphp/classes/class-qmn-quiz-manager.php, eliminating the unauthenticated access path for that AJAX action. - It added an explicit password protection check before allowing quiz submissions:
post_password_required($post_obj)is evaluated.current_user_can('edit_qsm_quizzes')is used to allow only editors to bypass that check.
- It changed
in_array()calls to use strict comparison by adding the third parametertrue:in_array('questions', $randomness_order, true)andin_array('pages', $randomness_order, true).
How do these changes fix the vulnerability?
- Removing the
noprivaction forcesqsm_get_quiz_to_reloadto require an authenticated session viawp_ajax_instead ofwp_ajax_nopriv_, closing the anonymous access vector. - The password protection check ensures that unauthenticated or unauthorized visitors cannot submit responses to password-protected quizzes through the plugin endpoint.
- Strict type checking prevents malformed input from bypassing internal logic that depends on array membership conditions, reducing the risk of unintended behavior.
Security improvements introduced
- Enforced authentication for sensitive AJAX handlers.
- Reinforced WordPress built-in content protection mechanisms before processing quiz submissions.
- Improved input handling by avoiding loose type coercion in array membership checks.
4. Proof of Concept (PoC) Guide
Prerequisites for exploitation
- A WordPress installation with QSM plugin version 10.3.1 or earlier.
- An unpublished/private/password-protected quiz present in the system.
- Access to the site over HTTP(S) and the ability to send requests to
admin-ajax.php.
Step-by-step exploitation approach
- Identify the vulnerable AJAX action.
- QSM uses actions such as
qsm_get_quiz_to_reload.
- QSM uses actions such as
- Send an unauthenticated request to the AJAX endpoint:
- Example:
GET /wp-admin/admin-ajax.php?action=qsm_get_quiz_to_reload&quiz_id=<ID>
- Example:
- Observe the response:
- If quiz data is returned without authentication, unauthorized access is confirmed.
- For file submission abuse, send an unauthenticated POST to the quiz response save endpoint with file payload fields.
- Include the quiz ID and response fields as expected by the plugin.
- If the server accepts the submission and returns success without requiring a password or login, the vulnerability is exploited.
Expected behavior vs exploited behavior
- Expected behavior: unauthenticated users should not be able to retrieve unpublished/private/protected quiz details or submit file responses to protected quizzes.
- Exploited behavior: unauthenticated requests successfully retrieve quiz data or submit responses, bypassing access control.
How to verify the vulnerability exists
- Confirm the plugin version is vulnerable.
- Execute the unauthenticated AJAX request and verify response content.
- Check whether a password-protected quiz rejects anonymous response submissions.
- Review server logs for anonymous accesses to QSM AJAX actions.
5. Recommendations
Mitigation strategies
- Upgrade QSM to the patched version that resolves CVE-2025-9637.
- Where immediate patching is impossible, disable access to vulnerable AJAX endpoints via web application firewall rules or plugin hardening.
- Restrict file upload handlers to authenticated users and validate quiz access status before accepting submissions.
Detection methods
- Monitor access logs for requests to
admin-ajax.phpwith QSM-specific actions from unauthenticated sources. - Alert on repeated access attempts to
qsm_get_quiz_to_reloador quiz response endpoints from external sources. - Scan WordPress installations for the plugin version and configuration of QSM endpoints.
Best practices to prevent similar issues
- Avoid registering unauthenticated AJAX endpoints for functionality that accesses protected content.
- Always enforce capability checks (
current_user_can) and content protection checks (post_password_required, post status) before processing requests. - Use nonces and authenticated endpoints for actions that modify or expose sensitive data.
- Apply strict input validation and type-safe comparisons to prevent bypasses through type coercion.
- Regularly audit plugin code for authorization and access control weaknesses, especially in AJAX and upload handlers.