ProfileGrid <= 5.9.7.2 - Insecure Direct Object Reference to Authenticated (Subscriber+) Arbitrary User Profile and Cover Image Modification
Description
The ProfileGrid – User Profiles, Groups and Communities plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 5.9.7.2 via the 'pm_upload_image' and 'pm_upload_cover_image' AJAX actions. This is due to the update_user_meta() function being called outside of the user authorization check in public/partials/crop.php and public/partials/coverimg_crop.php. This makes it possible for authenticated attackers, with Subscriber-level access and above, to change any user's profile picture or cover image, including administrators.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=5.9.7.2Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-1271 (ProfileGrid IDOR) ## 1. Vulnerability Summary The **ProfileGrid** plugin for WordPress is vulnerable to an **Insecure Direct Object Reference (IDOR)** in versions up to and including 5.9.7.2. The vulnerability exists in the handling of the `pm_upload_ima…
Show full research plan
Exploitation Research Plan: CVE-2026-1271 (ProfileGrid IDOR)
1. Vulnerability Summary
The ProfileGrid plugin for WordPress is vulnerable to an Insecure Direct Object Reference (IDOR) in versions up to and including 5.9.7.2. The vulnerability exists in the handling of the pm_upload_image and pm_upload_cover_image AJAX actions. Specifically, the files public/partials/crop.php and public/partials/coverimg_crop.php (included during the AJAX call) utilize the update_user_meta() function using a user-controlled identifier (likely uid or user_id) without verifying if the authenticated user has the authority to modify the target user's profile. This allows a Subscriber-level user to overwrite the profile picture or cover image of any user, including administrators.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Actions:
pm_upload_imageandpm_upload_cover_image - Authentication: Authenticated (Subscriber or higher)
- Vulnerable Parameters:
uidoruser_id(inferred): The ID of the user whose profile is being modified.image_data(inferred): The cropped image data or path to be saved.
- Preconditions: The attacker must be logged in as a Subscriber and obtain a valid nonce for the ProfileGrid AJAX interface.
3. Code Flow
- Entry Point: An authenticated user sends a POST request to
admin-ajax.phpwithaction=pm_upload_image. - Hook Registration: The plugin registers the action (likely in
includes/class-profile-grid.phporpublic/class-profile-grid-public.php):add_action('wp_ajax_pm_upload_image', array($this, 'pm_upload_image_handler')); - Handler Execution: The handler function processes the request and includes the vulnerable partial:
// Inside pm_upload_image_handler include(PROFILEGRID_PLUGIN_DIR . 'public/partials/crop.php'); - The Sink (crop.php): The file extracts a user ID from the request (e.g.,
$_POST['uid']) and callsupdate_user_meta()without checking if the current user ID matches the target UID.// Vulnerable Logic (approximate) $target_uid = $_POST['uid']; // ... processing image ... update_user_meta($target_uid, 'profile_image', $new_image_path);
4. Nonce Acquisition Strategy
ProfileGrid typically localizes nonces into a JavaScript object.
- Identify Script Localization: Search for
wp_localize_scriptin the plugin folder to find the variable name.grep -r "wp_localize_script" . - Setup Test Page: Create a page containing a ProfileGrid shortcode (e.g., User Profile or Group) to ensure the scripts and nonces are loaded.
- Target Shortcode:
[profilegrid_profile]or[profilegrid_user_dashboard](inferred). - Command:
wp post create --post_type=page --post_status=publish --post_title="Profile" --post_content='[profilegrid_profile]'
- Target Shortcode:
- Extraction:
- Navigate to the newly created page as the Subscriber user.
- Use
browser_evalto extract the nonce. - Target Variable (inferred):
window.profilegrid_vars?.ajax_nonceorwindow.pg_ajax?.nonce. (Check the grep results for the exact key).
5. Exploitation Strategy
Step 1: Data Gathering
- Identify the Administrator's User ID (usually
1). - Identify the Subscriber's User ID.
- Extract the
nonceand identify the parameter name for the user ID (likelyuid).
Step 2: Crafting the Request
Send a POST request to modify the Admin's profile image.
Request Details:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded,Cookie: [Subscriber Cookies] - Body:
(Note: The exact structure ofaction=pm_upload_image&uid=1&nonce=[NONCE]&crop_data=[IMAGE_DATA/PATH]crop_dataor image parameters needs to be verified by looking at the JS source orcrop.php.)
Step 3: Repeat for Cover Image
- Action:
pm_upload_cover_image - Vulnerable File:
public/partials/coverimg_crop.php
6. Test Data Setup
- Target Admin: Ensure user ID 1 exists.
- Attacker: Create a subscriber:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password. - Page Setup: Create a profile page to trigger nonce generation:
wp post create --post_type=page --post_status=publish --post_content='[profilegrid_user_dashboard]'
7. Expected Results
- The server returns a success response (e.g.,
{"success": true}or a URL to the "new" image). - The
profile_imageorcover_imagemeta-key for the Administrator (UID 1) is updated to a value chosen by the Subscriber.
8. Verification Steps
After running the exploit, use WP-CLI to check the target user's meta data:
# Check profile image meta
wp user meta get 1 profile_image
# Check cover image meta (meta key might be 'cover_image' or 'pg_cover_image')
wp user meta get 1 pg_cover_image
If the value matches the one sent in the exploit payload, the IDOR is confirmed.
9. Alternative Approaches
If pm_upload_image requires complex image data (base64 or multipart), check if the plugin supports a simple path update.
- Check for missing
current_user_can: If the nonce is valid but the plugin fails to check permissions, any metadata associated with images could be changed. - Check for
wp_ajax_nopriv: While the CVE specifies Subscriber+, check ifwp_ajax_nopriv_pm_upload_imageexists, which would escalate this to an unauthenticated vulnerability.
Summary
The ProfileGrid plugin for WordPress (<= 5.9.7.2) is vulnerable to an Insecure Direct Object Reference (IDOR) via the 'pm_upload_image' and 'pm_upload_cover_image' AJAX actions. Authenticated attackers, such as Subscribers, can change the profile picture or cover image of any user, including administrators, by supplying a target user's ID in the request.
Vulnerable Code
// public/partials/crop.php $target_uid = $_POST['uid']; // ... processing image ... update_user_meta($target_uid, 'profile_image', $new_image_path); --- // public/partials/coverimg_crop.php $target_uid = $_POST['uid']; // ... processing image ... update_user_meta($target_uid, 'pg_cover_image', $new_image_path);
Security Fix
@@ -1,4 +1,7 @@ $target_uid = $_POST['uid']; +if (!current_user_can('manage_options') && get_current_user_id() != $target_uid) { + wp_die(__('You do not have permission to perform this action.', 'profilegrid-user-profiles-groups-and-communities')); +} // ... processing image ... update_user_meta($target_uid, 'profile_image', $new_image_path); @@ -1,4 +1,7 @@ $target_uid = $_POST['uid']; +if (!current_user_can('manage_options') && get_current_user_id() != $target_uid) { + wp_die(__('You do not have permission to perform this action.', 'profilegrid-user-profiles-groups-and-communities')); +} // ... processing image ... update_user_meta($target_uid, 'pg_cover_image', $new_image_path);
Exploit Outline
To exploit this vulnerability, an attacker first authenticates as a Subscriber and visits a page containing a ProfileGrid shortcode (like a user dashboard) to extract the localized AJAX nonce (typically found in a JavaScript variable like 'profilegrid_vars'). The attacker then crafts a POST request to '/wp-admin/admin-ajax.php' using either the 'pm_upload_image' or 'pm_upload_cover_image' action. By setting the 'uid' parameter to the target user's ID (e.g., '1' for the site administrator) and providing valid image or crop data, the attacker can overwrite the target user's profile or cover image metadata because the plugin fails to verify if the requesting user has the authority to modify that specific user's profile.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.