WP Document Revisions <= 3.8.1 - 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 versions up to, and including, 3.8.1. This makes it possible for unauthenticated attackers to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=3.8.1What Changed in the Fix
Changes introduced in v4.0.0
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-42677 (WP Document Revisions) ## 1. Vulnerability Summary The **WP Document Revisions** plugin (versions <= 3.8.1) contains a missing authorization vulnerability in the function `update_post_slug_field`. This function is intended to allow users to update the U…
Show full research plan
Exploitation Research Plan: CVE-2026-42677 (WP Document Revisions)
1. Vulnerability Summary
The WP Document Revisions plugin (versions <= 3.8.1) contains a missing authorization vulnerability in the function update_post_slug_field. This function is intended to allow users to update the URL slug (permalink) of a document post. However, because it lacks both capability checks (current_user_can) and potentially nonce verification, unauthenticated attackers can invoke this function via the WordPress AJAX API to modify the slug of any document.
This can lead to broken links, disruption of document workflows, and potential bypasses of access controls that rely on specific URL structures.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
update_post_slug_field(Inferred from the function name indocs/changelog.md) - Vulnerable Hook:
wp_ajax_nopriv_update_post_slug_field(likely registered without restriction) orwp_ajax_update_post_slug_field(missing capability check inside the handler). - HTTP Method:
POST - Authentication: None (Unauthenticated)
- Preconditions: The attacker must know the
IDof a "Document" post. This is often discoverable via the REST API (/wp-json/wp/v2/documents) if enabled, or by iterating through post IDs.
3. Code Flow
The expected execution path is:
- Entry Point: An unauthenticated
POSTrequest is sent toadmin-ajax.phpwith theactionparameter set toupdate_post_slug_field. - Hook Execution: WordPress triggers the action handler associated with
wp_ajax_nopriv_update_post_slug_field(or thewp_ajax_variant if the user is logged in but lacks permissions). - Vulnerable Sink: The handler calls
update_post_slug_field(). - Missing Check: Based on the fix description in
docs/changelog.md(Version 3.8.0), the functionupdate_post_slug_fieldfails to verify if the requester has theedit_documentscapability or if the request is legitimate via a nonce. - Modification: The function proceeds to call
wp_update_post()or modifies thepost_namefield in the database directly for the specifiedpost_id.
4. Nonce Acquisition Strategy
If the plugin requires a nonce (even if it fails to check permissions), it is likely localized via wp_localize_script. Since this is an unauthenticated vulnerability, we must look for a nonce exposed to the frontend.
- Identify Script Handle: The plugin likely uses a handle like
wp-document-revisionsordocument-revisions-admin. - Shortcode Page: Create a page containing a Document shortcode to ensure the plugin's environment is loaded.
wp post create --post_type=page --post_status=publish --post_content='[documents]'
- Browser Extraction:
- Navigate to the newly created page.
- Use
browser_evalto search for the nonce variable. Based on common WordPress plugin patterns, it might be inside a global object. - Target Variable (Inferred):
window.WPDocumentRevisions?.ajax_nonceorwindow.wp_dr_params?.nonce. - Note: If the vulnerability is truly "Missing Authorization" for unauthenticated users, the
wp_ajax_noprivhandler may not be checking the nonce at all, or using a default action.
5. Exploitation Strategy
We will attempt to change the slug of an existing document from original-slug to pwned-slug.
Step 1: Discover Target Document
Identify a valid Document ID.
wp post list --post_type=document --fields=ID,post_name
Step 2: Perform the Attack
Send an unauthenticated request to the AJAX endpoint.
HTTP Request (Conceptual):
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=update_post_slug_fieldpost_id=[TARGET_ID]new_slug=pwned-document-urlnonce=[EXTRACTED_NONCE](If required)
Step 3: Payload Implementation (via http_request tool)
# Implementation for the security agent
params = {
"action": "update_post_slug_field",
"post_id": 123, # Replace with discovered ID
"new_slug": "pwned-slug"
}
# Use http_request to send the POST
6. Test Data Setup
To verify the exploit, the environment must contain:
- Document Post: A document with a known ID and slug.
wp post create --post_type=document --post_title="Sensitive Document" --post_name="sensitive-doc" --post_status=publish
- Permalinks: Ensure permalinks are enabled (e.g., Post Name) so slug changes are visible.
wp rewrite structure '/%postname%/'
7. Expected Results
- Success: The HTTP response returns
1,true, or a success JSON (e.g.,{"success":true}). - Database Change: The
post_namefield for the document ID in thewp_poststable is updated topwned-slug. - Visibility: Navigating to the original URL (
/documents/sensitive-doc/) results in a 404, while the new URL (/documents/pwned-slug/) loads the document.
8. Verification Steps
After the exploit, verify the change using WP-CLI:
# Check if the slug was updated
wp post get [ID] --field=post_name
# Verify the new permalink
wp post list --post_type=document --post_id=[ID] --fields=ID,post_name,guid
9. Alternative Approaches
If the action name is not update_post_slug_field:
- Grep for AJAX Actions:
grep -rn "wp_ajax" .in the plugin directory to find the actual registered action name. - Check Parameter Names: If
new_slugfails, tryslug,post_name, ornew_post_slug. - REST API: Check if a similar missing authorization exists on the REST route:
POST /wp-json/wp-document-revisions/v1/update-slug(inferred path). - Referer Header: Some WordPress AJAX handlers check
HTTP_REFERER. If the request fails, try setting the Referer to the site's home page or admin page.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.