Document Revisions <= 3.7.2 - Missing Authorization
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:NTechnical Details
<=3.7.2Source Code
WordPress.org SVNThis 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_postfunction 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 specificpost_id.
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin-ajax.phporwp-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:
- The attacker must have an account with the Author role.
- A "Document" (custom post type
document) must exist that is not owned by the Author (e.g., owned by Admin).
3. Code Flow (Inferred)
- Registration: The plugin registers AJAX handlers in
includes/class-wp-document-revisions-admin.phpor the main plugin file usingadd_action( 'wp_ajax_...' ). - Entry Point: The Author user sends a POST request to
admin-ajax.phpwith a valid nonce and apost_idbelonging to an Admin-owned document. - 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 (likeedit_posts) instead of a document-specific one.
- The handler calls
- The Sink: The code proceeds to update the document using
wp_update_post()orupdate_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.
- Identify Shortcode/Script: WP Document Revisions typically enqueues scripts on the Document Edit or List pages.
- Creation: The agent should ensure at least one document exists that the Author can view (or create one as the Author).
- Navigation: Log in as the Author and navigate to the Documents list:
wp-admin/edit.php?post_type=document. - Extraction:
- Look for
wp_localize_scriptdata in the page source. - Common localization keys for this plugin:
dr_vars,wp_dr_params, ordocument_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.
- Look for
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:
- Identify Action: Search for
add_action( 'wp_ajax_...in the plugin code. Likely candidates:wp_dr_change_statuswp_document_revisions_save_metaboxwp_dr_rename_document
- Craft Request:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method: POST
- Content-Type:
application/x-www-form-urlencoded - Payload (Example):
Note: Replaceaction=wp_dr_rename_document&post_id=[TARGET_ID]&new_title=PwnedByAuthor&security=[NONCE]wp_dr_rename_documentandsecuritywith the actual action and nonce key found during discovery.
- URL:
6. Test Data Setup
- 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).
- Attacker Account: Create an Author user:
wp user create attacker attacker@example.com --role=author --user_pass=password123
- 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:
- Check Title:
wp post get [TARGET_ID] --field=post_title - Check Status:
wp post get [TARGET_ID] --field=post_status - 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 throughpost_idsfrom$_REQUESTwithout 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_metacalls inincludes/class-wp-document-revisions-admin.phpthat are not wrapped in acurrent_user_can( 'edit_post', $post_id )block.
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
@@ -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.