CVE-2026-4057

Download Manager <= 3.3.51 - Missing Authorization to Authenticated (Contributor+) Media File Protection Removal

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
3.3.52
Patched in
1d
Time to patch

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: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.3.51
PublishedApril 9, 2026
Last updatedApril 10, 2026
Affected plugindownload-manager

What Changed in the Fix

Changes introduced in v3.3.52

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

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 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_public and wpdm_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)

  1. Entry Point: An authenticated user (Contributor+) sends a POST request to admin-ajax.php with the action wpdm_make_media_public.
  2. Hook Registration: The plugin registers the action (likely in src/MediaLibrary/MediaHandler.php or src/wpdm-core.php):
    add_action('wp_ajax_wpdm_make_media_public', array($this, 'makeMediaPublic'));
  3. Capability Check: Inside makeMediaPublic(), the code checks current_user_can('edit_posts'). This returns true for Contributors.
  4. Missing Ownership Check: The code retrieves the $id from $_REQUEST['id']. It fails to perform current_user_can('edit_post', $id).
  5. Metadata Deletion: The function proceeds to call delete_post_meta($id, ...) for keys such as __wpdm_lock, __wpdm_password, and __wpdm_access.
  6. 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.

  1. Identify the Script: WPDM enqueues scripts for the media library.
  2. 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.
  3. 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).
  4. Extract via Browser:
    // In the browser console of the Contributor user
    console.log(window.wpdm_js?.nonce || window.wpdm_admin?.nonce);
    
    Note: If the nonce is strictly required, the agent should search src/MediaLibrary/MediaHandler.php for check_ajax_referer to identify the expected parameter name (usually __wpdm_media_auth or 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:
    action=wpdm_make_media_public&id=[TARGET_MEDIA_ID]&__wpdm_media_auth=[NONCE]
    
    (Note: Replace __wpdm_media_auth with 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

  1. Admin User: Create a media file (Attachment).
  2. 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');
  3. Contributor User: Create a user with the contributor role.
  4. Nonce Page: Create a page using wp post create that 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:

  1. Search src/MediaLibrary/MediaHandler.php for add_action calls.
  2. If edit_posts isn't sufficient, try the exploit with an Author account.
  3. If a nonce is not found in the global JS object, check if the function makeMediaPublic calls check_ajax_referer. If it doesn't, the exploit can be performed without a nonce.
  4. Try the wpdm_make_media_private action to see if it allows modifying settings on files the user doesn't own (same vulnerability, different direction).
Research Findings
Static analysis — not yet PoC-verified

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

--- src/MediaLibrary/MediaHandler.php
+++ src/MediaLibrary/MediaHandler.php
@@ -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.