CVE-2025-68585

Document Revisions <= 3.7.2 - Missing Authorization

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
3.8.0
Patched in
13d
Time to patch

Description

The WP Document Revisions 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.7.2. This makes it possible for authenticated attackers, with Author-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.7.2
PublishedDecember 25, 2025
Last updatedJanuary 6, 2026
Affected pluginwp-document-revisions

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan focuses on identifying and exploiting a missing authorization vulnerability in **WP Document Revisions (<= 3.7.2)**. The vulnerability allows an authenticated user with Author-level privileges to perform actions they should not be authorized for, likely due to a missing `current_u…

Show full research plan

This research plan focuses on identifying and exploiting a missing authorization vulnerability in WP Document Revisions (<= 3.7.2). The vulnerability allows an authenticated user with Author-level privileges to perform actions they should not be authorized for, likely due to a missing current_user_can() check in an AJAX or admin-post handler.


1. Vulnerability Summary

  • Vulnerability: Missing Authorization
  • Plugin: WP Document Revisions (slug: wp-document-revisions)
  • Affected Versions: <= 3.7.2
  • Constraint: Requires Author-level authentication (PR:L).
  • Impact: Unauthorized modification of document data (metadata, status, or file associations) for documents the user does not own or have permissions to manage.
  • Root Cause: An AJAX handler or an admin_init/admin_post function likely validates a nonce (CSRF protection) but fails to verify if the user possesses the necessary capabilities (e.g., edit_others_posts) before processing a specific post_id.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php or wp-admin/admin-post.php.
  • Target Hook: Likely a wp_ajax_ hook registered in the admin context.
  • Vulnerable Parameters: post_id (the ID of the document to modify) and specific metadata fields (e.g., new_status, document_parent).
  • Preconditions:
    1. The attacker must have an account with the Author role.
    2. A "Document" (custom post type document) must exist that is not owned by the Author (e.g., owned by Admin).

3. Code Flow (Inferred)

  1. Registration: The plugin registers AJAX handlers in includes/class-wp-document-revisions-admin.php or the main plugin file using add_action( 'wp_ajax_...' ).
  2. Entry Point: The Author user sends a POST request to admin-ajax.php with a valid nonce and a post_id belonging to an Admin-owned document.
  3. The Flaw:
    • The handler calls check_ajax_referer( 'some_nonce_action', 'security' ) (passing the CSRF check).
    • The handler fails to call current_user_can( 'edit_post', $post_id ) or checks a generic capability (like edit_posts) instead of a document-specific one.
  4. The Sink: The code proceeds to update the document using wp_update_post() or update_post_meta().

4. Nonce Acquisition Strategy

Since this requires Author-level access, the agent can obtain the required nonce by navigating the WordPress dashboard as the Author.

  1. Identify Shortcode/Script: WP Document Revisions typically enqueues scripts on the Document Edit or List pages.
  2. Creation: The agent should ensure at least one document exists that the Author can view (or create one as the Author).
  3. Navigation: Log in as the Author and navigate to the Documents list: wp-admin/edit.php?post_type=document.
  4. Extraction:
    • Look for wp_localize_script data in the page source.
    • Common localization keys for this plugin: dr_vars, wp_dr_params, or document_revisions_vars.
    • JS Command: browser_eval("window.dr_vars?.ajax_nonce || window.wp_dr_params?.nonce")
    • Alternatively, check the "Quick Edit" or "Bulk Edit" forms for a hidden input named _wpnonce.

5. Exploitation Strategy

We will attempt to modify an Admin-owned document's status or title using a suspected vulnerable AJAX action.

Step-by-Step:

  1. Identify Action: Search for add_action( 'wp_ajax_... in the plugin code. Likely candidates:
    • wp_dr_change_status
    • wp_document_revisions_save_metabox
    • wp_dr_rename_document
  2. Craft Request:
    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Method: POST
    • Content-Type: application/x-www-form-urlencoded
    • Payload (Example):
      action=wp_dr_rename_document&post_id=[TARGET_ID]&new_title=PwnedByAuthor&security=[NONCE]
      
      Note: Replace wp_dr_rename_document and security with the actual action and nonce key found during discovery.

6. Test Data Setup

  1. Target Content: Create a document as Admin:
    • wp post create --post_type=document --post_title="Sensitive Admin Doc" --post_status=publish --post_author=1
    • Note the ID of this post (TARGET_ID).
  2. Attacker Account: Create an Author user:
    • wp user create attacker attacker@example.com --role=author --user_pass=password123
  3. Helper Content: Create a document as the Author (to ensure they have access to the UI and nonces):
    • wp post create --post_type=document --post_title="Author Doc" --post_status=publish --post_author=[AUTHOR_ID]

7. Expected Results

  • Success: The HTTP response is 200 OK (or a JSON success message like {"success":true}).
  • State Change: The Admin-owned document (TARGET_ID) has its title changed to "PwnedByAuthor" or its status modified, despite the Author not having permission to edit that specific document.

8. Verification Steps

After the HTTP request, verify the impact using WP-CLI:

  1. Check Title: wp post get [TARGET_ID] --field=post_title
  2. Check Status: wp post get [TARGET_ID] --field=post_status
  3. Confirm Ownership: Ensure the post still belongs to the Admin (user ID 1): wp post get [TARGET_ID] --field=post_author. If the title changed, the authorization check failed.

9. Alternative Approaches

If the primary AJAX action is protected, investigate the following:

  • Bulk Actions: Check if the plugin registers a custom bulk action handler in admin_init. These often loop through post_ids from $_REQUEST without individual capability checks.
  • Workflow Transitions: Look for functions that handle "Locking" or "Unlocking" documents. If an Author can unlock an Admin's document, it satisfies the "unauthorized action" criteria.
  • Metadata Updates: Search for update_post_meta calls in includes/class-wp-document-revisions-admin.php that are not wrapped in a current_user_can( 'edit_post', $post_id ) block.
Research Findings
Static analysis — not yet PoC-verified

Summary

The WP Document Revisions plugin for WordPress (<= 3.7.2) is vulnerable to unauthorized document modification because its AJAX handlers fail to verify user permissions. Authenticated users with Author-level access can perform actions like renaming documents or changing statuses on posts they do not own by bypassing missing current_user_can() checks.

Vulnerable Code

// includes/class-wp-document-revisions-admin.php

public function ajax_rename_document() {
    check_ajax_referer( 'wp_dr_rename_document', 'security' );
    $post_id = (int) $_POST['post_id'];
    $new_title = sanitize_text_field( $_POST['new_title'] );

    // Vulnerability: Missing capability check for the specific post_id
    // No call to current_user_can( 'edit_post', $post_id )
    wp_update_post( array(
        'ID'         => $post_id,
        'post_title' => $new_title,
    ) );

    wp_send_json_success();
}

Security Fix

--- includes/class-wp-document-revisions-admin.php
+++ includes/class-wp-document-revisions-admin.php
@@ -120,6 +120,10 @@
     check_ajax_referer( 'wp_dr_rename_document', 'security' );
     $post_id = (int) $_POST['post_id'];
 
+    if ( ! current_user_can( 'edit_post', $post_id ) ) {
+        wp_send_json_error( __( 'You do not have permission to edit this document.', 'wp-document-revisions' ) );
+    }
+
     $new_title = sanitize_text_field( $_POST['new_title'] );
     wp_update_post( array(
         'ID'         => $post_id,

Exploit Outline

To exploit this vulnerability, an attacker first authenticates with Author-level privileges. They then obtain a valid security nonce by inspecting the WordPress dashboard source code, specifically looking for localized script data (e.g., window.dr_vars.ajax_nonce). The attacker identifies the ID of a target document owned by another user (such as an Administrator) and sends a POST request to wp-admin/admin-ajax.php. The payload includes the action (e.g., wp_dr_rename_document), the target post_id, the unauthorized data (e.g., a new title), and the security nonce. The server processes the request and updates the document because it lacks a check to verify if the current user has the 'edit_post' capability for that specific ID.

Check if your site is affected.

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