Download Manager <= 3.3.51 - Missing Authorization to Authenticated (Contributor+) Media File Protection Removal
Description
The Download Manager plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the `makeMediaPublic()` and `makeMediaPrivate()` functions in all versions up to, and including, 3.3.51. This is due to the functions only checking for `edit_posts` capability without verifying post ownership via `current_user_can('edit_post', $id)`, and the destructive operations executing before the admin-level check in `mediaAccessControl()`. This makes it possible for authenticated attackers, with Contributor-level access and above, to strip all protection metadata (password, access restrictions, private flag) from any media file they do not own, making admin-protected files publicly accessible via their direct URL.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=3.3.51What Changed in the Fix
Changes introduced in v3.3.52
Source Code
WordPress.org SVNThis research plan outlines the technical steps required to exploit **CVE-2026-4057** in WordPress Download Manager <= 3.3.51. ## 1. Vulnerability Summary The vulnerability is a **Missing Authorization** flaw within the media protection features of the Download Manager plugin. Specifically, the fun…
Show full research plan
This research plan outlines the technical steps required to exploit CVE-2026-4057 in WordPress Download Manager <= 3.3.51.
1. Vulnerability Summary
The vulnerability is a Missing Authorization flaw within the media protection features of the Download Manager plugin. Specifically, the functions makeMediaPublic() and makeMediaPrivate() (likely located within WPDM\MediaLibrary\MediaHandler) verify if a user has the edit_posts capability (possessed by Contributors and above) but fail to verify if the user has permission to edit the specific post/attachment ID provided (edit_post).
Because these functions execute their metadata-stripping logic before broader access control checks, a Contributor can remove protection settings (passwords, role restrictions) from media files owned by Administrators, rendering them accessible via direct URL.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - AJAX Actions:
wpdm_make_media_publicandwpdm_make_media_private(inferred from function names and WPDM naming conventions). - Required Parameter:
id(The WordPress Attachment/Post ID of the media file). - Authentication: Authenticated, minimum level Contributor.
- Preconditions: A media file must be uploaded by an Admin and protected using WPDM's Media Library protection features.
3. Code Flow (Trace)
- Entry Point: An authenticated user (Contributor+) sends a POST request to
admin-ajax.phpwith the actionwpdm_make_media_public. - Hook Registration: The plugin registers the action (likely in
src/MediaLibrary/MediaHandler.phporsrc/wpdm-core.php):add_action('wp_ajax_wpdm_make_media_public', array($this, 'makeMediaPublic')); - Capability Check: Inside
makeMediaPublic(), the code checkscurrent_user_can('edit_posts'). This returnstruefor Contributors. - Missing Ownership Check: The code retrieves the
$idfrom$_REQUEST['id']. It fails to performcurrent_user_can('edit_post', $id). - Metadata Deletion: The function proceeds to call
delete_post_meta($id, ...)for keys such as__wpdm_lock,__wpdm_password, and__wpdm_access. - Result: The attachment is no longer "locked" by WPDM, and its direct file path/URL becomes unprotected.
4. Nonce Acquisition Strategy
WPDM usually localizes nonces into the wpdm_js or wpdm_admin object for use in the media library interface.
- Identify the Script: WPDM enqueues scripts for the media library.
- Create Test Page: To ensure the script is enqueued for a Contributor, create a post with a WPDM-related shortcode or navigate to a WPDM admin page.
- Search for Nonce:
- Use
grep -r "wp_create_nonce" src/to find the action string used for media protection. - Common WPDM nonce action:
__wpdm_media_auth(inferred).
- Use
- Extract via Browser:
Note: If the nonce is strictly required, the agent should search// In the browser console of the Contributor user console.log(window.wpdm_js?.nonce || window.wpdm_admin?.nonce);src/MediaLibrary/MediaHandler.phpforcheck_ajax_refererto identify the expected parameter name (usually__wpdm_media_author similar).
5. Exploitation Strategy
Step 1: Target Identification
Find the ID of a protected media file uploaded by the Administrator. If not known, create one in the setup phase.
Step 2: Request Construction
Send a request to make the media public as the Contributor.
HTTP Request:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
(Note: Replaceaction=wpdm_make_media_public&id=[TARGET_MEDIA_ID]&__wpdm_media_auth=[NONCE]__wpdm_media_authwith the actual nonce key found during research).
Step 3: Verify Metadata Stripping
Check if the specific WPDM protection meta keys are removed from the database for that ID.
6. Test Data Setup
- Admin User: Create a media file (Attachment).
- Protect Media: Use WPDM to protect the media.
- Set a password:
update_post_meta($media_id, '__wpdm_password', 'secret123'); - Set lock:
update_post_meta($media_id, '__wpdm_lock', '1');
- Set a password:
- Contributor User: Create a user with the
contributorrole. - Nonce Page: Create a page using
wp post createthat includes a[wpdm_direct_link id=...]shortcode to force script enqueuing if necessary.
7. Expected Results
- Response: The server should return a success message (likely JSON
{"success": true}or a string "1"). - Database Change: The post meta entries for
__wpdm_lock,__wpdm_password, etc., for the target ID should be deleted. - Access Change: A direct request to the media file or the WPDM download URL that previously required a password should now serve the file immediately without a prompt.
8. Verification Steps
After running the exploit via http_request, verify the state using wp-cli:
# Check if protection metadata still exists
wp post meta get [TARGET_MEDIA_ID] __wpdm_lock
wp post meta get [TARGET_MEDIA_ID] __wpdm_password
# Expected: "Error: Could not find the metadata for key..."
9. Alternative Approaches
If wpdm_make_media_public is not the correct action name:
- Search
src/MediaLibrary/MediaHandler.phpforadd_actioncalls. - If
edit_postsisn't sufficient, try the exploit with an Author account. - If a nonce is not found in the global JS object, check if the function
makeMediaPubliccallscheck_ajax_referer. If it doesn't, the exploit can be performed without a nonce. - Try the
wpdm_make_media_privateaction to see if it allows modifying settings on files the user doesn't own (same vulnerability, different direction).
Summary
The Download Manager plugin for WordPress is vulnerable to unauthorized modification of data due to a missing authorization check in its media protection removal logic. This allows authenticated users with Contributor-level privileges and above to strip passwords, locks, and access restrictions from media files they do not own, making admin-protected files publicly accessible via direct URLs.
Security Fix
@@ -134,7 +134,8 @@ function makeMediaPublic() { - if (!current_user_can('edit_posts')) { + $id = (int)$_REQUEST['id']; + if (!current_user_can('edit_post', $id)) { die('Unauthorized'); } - $id = (int)$_REQUEST['id']; delete_post_meta($id, "__wpdm_lock"); delete_post_meta($id, "__wpdm_password"); delete_post_meta($id, "__wpdm_access"); @@ -148,7 +149,8 @@ function makeMediaPrivate() { - if (!current_user_can('edit_posts')) { + $id = (int)$_REQUEST['id']; + if (!current_user_can('edit_post', $id)) { die('Unauthorized'); } - $id = (int)$_REQUEST['id']; update_post_meta($id, "__wpdm_lock", 1);
Exploit Outline
The exploit targets the `wpdm_make_media_public` or `wpdm_make_media_private` AJAX actions. An attacker must be authenticated as a Contributor or higher. The attacker first identifies the WordPress Attachment ID of a protected media file owned by an administrator. They then obtain a valid AJAX nonce (commonly localized as `wpdm_js.nonce` or used in the media library interface). By sending a POST request to `/wp-admin/admin-ajax.php` with the target `id` and the `action` parameter set to `wpdm_make_media_public`, the attacker triggers the deletion of protection metadata (`__wpdm_lock`, `__wpdm_password`, `__wpdm_access`) for the target ID. Because the plugin only verifies the general `edit_posts` capability and fails to verify specific ownership for the provided ID, the operation completes successfully, rendering the file publicly accessible.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.