CVE-2025-68997

wpDiscuz <= 7.6.42 - Unauthenticated Insecure Direct Object Reference

mediumAuthorization Bypass Through User-Controlled Key
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
7.6.44
Patched in
27d
Time to patch

Description

The Comments – wpDiscuz plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 7.6.42 due to missing validation on a user controlled key. This makes it possible for unauthenticated attackers to perform unauthorized actions.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=7.6.42
PublishedDecember 25, 2025
Last updatedJanuary 20, 2026
Affected pluginwpdiscuz

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2025-68997 (wpDiscuz IDOR) ## 1. Vulnerability Summary The **Comments – wpDiscuz** plugin for WordPress is vulnerable to an **Insecure Direct Object Reference (IDOR)** in versions up to and including 7.6.42. The vulnerability exists in the handling of unauthentica…

Show full research plan

Exploitation Research Plan - CVE-2025-68997 (wpDiscuz IDOR)

1. Vulnerability Summary

The Comments – wpDiscuz plugin for WordPress is vulnerable to an Insecure Direct Object Reference (IDOR) in versions up to and including 7.6.42. The vulnerability exists in the handling of unauthenticated AJAX actions related to comment subscriptions and follows (specifically the wpdUnsubscribe or wpdCancelFollow actions).

The plugin fails to properly validate that a user-provided "key" (intended to authorize an action on a specific resource) actually corresponds to the resource ID being manipulated. An unauthenticated attacker can provide their own valid key (or potentially an arbitrary one) alongside a victim's subscription ID to perform unauthorized actions, such as unsubscribing other users from comment threads.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: wpdUnsubscribe (inferred from common wpDiscuz subscription workflows) or wpdCancelFollow.
  • Method: POST
  • Payload Parameters:
    • action: wpdUnsubscribe
    • sId: The numeric ID of the subscription to be canceled (Object Reference).
    • sKey: A key used for authorization (User-Controlled Key).
    • nonce: A valid WordPress nonce for the AJAX action.
  • Authentication: Unauthenticated (wp_ajax_nopriv_ hook).
  • Preconditions: At least one active comment subscription must exist in the database for the victim.

3. Code Flow

  1. Entry Point: An unauthenticated user sends a POST request to admin-ajax.php with action=wpdUnsubscribe.
  2. Hook Registration: The plugin registers the handler in includes/class-wpdiscuz-ajax.php (or includes/class.wpDiscuz.php) using:
    add_action('wp_ajax_nopriv_wpdUnsubscribe', array($this, 'wpdUnsubscribe'));
  3. Handler Execution: The wpdUnsubscribe() function retrieves sId and sKey from the $_POST array.
  4. The Sink: The code likely checks if sKey is present but fails to verify that sKey is the specific key associated with the record identified by sId in the {$wpdb->prefix}wc_comments_subscription table.
  5. Unauthorized Action: The plugin proceeds to call a database method (e.g., $this->dbManager->unsubscribe($sId)) which deletes the subscription record regardless of whether the key matches that specific ID.

4. Nonce Acquisition Strategy

The wpDiscuz plugin enqueues a central JavaScript object containing configuration and nonces on any page where comments are active.

  1. Identify Script Loading: The script wpdiscuz-ajax-js is typically loaded on any post or page with comments enabled.
  2. Setup Post: Create a post that allows comments.
    wp post create --post_type=post --post_title="Vuln Test" --post_status=publish --comment_status=open
    
  3. Navigate and Extract:
    • Use browser_navigate to visit the newly created post.
    • Use browser_eval to extract the nonce from the wpdiscuzAjaxObj global variable.
    • JavaScript Variable: window.wpdiscuzAjaxObj
    • Nonce Key: nonce
    • Command: browser_eval("window.wpdiscuzAjaxObj?.nonce")
  4. Note: If wpdiscuzAjaxObj is not found, check for wpdiscuz_options or similar localized strings in the page source.

5. Exploitation Strategy

  1. Setup Victim Data: Create a subscription for a victim email address to generate a valid sId in the database.
  2. Setup Attacker Data: Create a separate subscription for an attacker email address to obtain a "valid" sKey (if the plugin requires any valid key) or simply use an arbitrary string if the check is completely missing.
  3. Trigger IDOR:
    • Construct a POST request to admin-ajax.php.
    • Set sId to the Victim's ID (which is usually an incremental integer).
    • Set sKey to the Attacker's key or a random string.
    • Include the nonce obtained in Step 4.
  4. HTTP Request Details:
    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Method: POST
    • Headers: Content-Type: application/x-www-form-urlencoded
    • Body: action=wpdUnsubscribe&sId=[VICTIM_SID]&sKey=[ATTACKER_SKEY]&nonce=[NONCE]

6. Test Data Setup

  1. Enable Plugin: Ensure wpdiscuz is active.
  2. Generate Subscriptions:
    The easiest way to populate the table {$wpdb->prefix}wc_comments_subscription for testing is via wp eval:
    global $wpdb;
    $table = $wpdb->prefix . "wc_comments_subscription";
    // Victim Subscription (ID will be 1)
    $wpdb->insert($table, ['post_id' => 1, 'email' => 'victim@example.com', 'subscription_type' => 'all', 'confirm_key' => 'victim_key', 'status' => 1]);
    // Attacker Subscription (ID will be 2)
    $wpdb->insert($table, ['post_id' => 1, 'email' => 'attacker@example.com', 'subscription_type' => 'all', 'confirm_key' => 'attacker_key', 'status' => 1]);
    
  3. Confirm IDs: Verify the IDs using wp db query "SELECT * FROM wp_wc_comments_subscription".

7. Expected Results

  • Successful Request: The server returns a JSON response (e.g., {"success":true}) or a successful status indicator used by wpDiscuz.
  • Database Impact: The record in the wp_wc_comments_subscription table corresponding to the sId of the victim is deleted or its status is changed, even though the attacker did not provide the victim's secret key.

8. Verification Steps

  1. Check Database: After the exploit request, run:
    wp db query "SELECT count(*) FROM wp_wc_comments_subscription WHERE email='victim@example.com'"
    
  2. Success Condition: The count should be 0 (if deleted) or the status should be changed, indicating the IDOR was successful.

9. Alternative Approaches

  • Action Variation: If wpdUnsubscribe is not the correct action name, investigate wpdCancelFollow or wpdUnfollowUser in includes/class-wpdiscuz-ajax.php.
  • Key Discovery: If the plugin validates that the sKey must be a valid key from the database (but not necessarily the right one for that ID), the strategy of using the Attacker's own valid sKey to delete the Victim's sId is the primary fallback.
  • Brute Force sId: Since sId is likely an auto-incrementing integer, an attacker can iterate through IDs (e.g., 1-100) to mass-unsubscribe users.
Research Findings
Static analysis — not yet PoC-verified

Summary

The wpDiscuz plugin for WordPress is vulnerable to an Insecure Direct Object Reference (IDOR) in versions up to and including 7.6.42. This allows unauthenticated attackers to perform unauthorized actions, such as unsubscribing other users from comment threads, due to a failure to validate that a provided authorization key matches the specific subscription record being accessed.

Exploit Outline

The vulnerability occurs within unauthenticated AJAX handlers responsible for subscription management. An attacker can initiate a request to modify a subscription by referencing its numeric ID. Because the application does not properly verify the relationship between the subscription ID and the authorization key provided in the request, the attacker can successfully perform actions on records they do not own by supplying their own key or a generic value.

Check if your site is affected.

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