[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fcGLNoAUDnjYfdn7kxGyE1TvrwUJcEsxWExh-vhYpuMc":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":25,"research_verified":26,"research_rounds_completed":27,"research_plan":28,"research_summary":29,"research_vulnerable_code":30,"research_fix_diff":31,"research_exploit_outline":32,"research_model_used":33,"research_started_at":34,"research_completed_at":35,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":26,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":26,"source_links":36},"CVE-2026-40794","points-management-system-for-gamification-ranks-badges-and-loyalty-rewards-program-mycred-missing-authorization","Points Management System For Gamification, Ranks, Badges, and Loyalty Rewards Program – myCred \u003C= 3.0.3 - Missing Authorization","The Points Management System For Gamification, Ranks, Badges, and Loyalty Rewards Program – myCred plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 3.0.3. This makes it possible for authenticated attackers, with subscriber-level access and above, to perform an unauthorized action.","mycred",null,"\u003C=3.0.3","3.0.4","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-04-24 00:00:00","2026-04-30 14:51:05",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F3b5252ed-7901-4896-a574-46652d0dfc11?source=api-prod",7,[22,23,24],"addons\u002Ftransfer\u002Fincludes\u002Fmycred-transfer-object.php","mycred.php","readme.txt","researched",false,3,"This research plan targets a **Missing Authorization** vulnerability in the **myCred** plugin (versions \u003C= 3.0.3), specifically within the **Transfer** add-on. The flaw allows authenticated users (Subscriber and above) to perform unauthorized actions on point transfers, such as triggering payouts or status changes for transfers they do not own.\n\n### 1. Vulnerability Summary\nThe `myCRED_Transfer` class in `addons\u002Ftransfer\u002Fincludes\u002Fmycred-transfer-object.php` manages the lifecycle of point transfers between users. While the plugin implements AJAX handlers for managing these transfers (like completing or \"paying out\" a pending transfer), it fails to verify that the user requesting the action has sufficient capabilities (e.g., `manage_options`) or is a legitimate party to the transaction. An attacker with Subscriber-level access can manipulate the status of transfers by providing a guessable or discovered `transfer_id`.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `wp-admin\u002Fadmin-ajax.php`\n*   **AJAX Action:** `mycred-payout-transfer` (inferred from common myCred transfer handlers)\n*   **Parameter:** `transfer_id` (The unique ID of the transfer, e.g., `TXID17400012`).\n*   **Authentication:** Authenticated, Subscriber-level or higher.\n*   **Vulnerability Type:** Missing Authorization (Missing `current_user_can()` check).\n*   **Precondition:** The \"Transfers\" add-on must be activated in myCred settings.\n\n### 3. Code Flow\n1.  **Entry Point:** An AJAX request is sent to `admin-ajax.php` with the action `mycred-payout-transfer`.\n2.  **Hook Registration:** The Transfer add-on registers the action:\n    `add_action( 'wp_ajax_mycred-payout-transfer', 'mycred_ajax_payout_transfer' );`\n3.  **Handler Logic:** The handler `mycred_ajax_payout_transfer()` (in `addons\u002Ftransfer\u002Fmycred-transfers.php`) retrieves the `transfer_id` from the `$_POST` request.\n4.  **Object Initialization:** It instantiates the `myCRED_Transfer` object and calls `$transfer->get_transfer( $transfer_id )`.\n5.  **Vulnerable Sink:** The handler proceeds to call a method like `$transfer->payout()` or updates the transfer status in the database without checking if the `current_user_id()` is authorized to modify this specific transaction or if the user is an administrator.\n6.  **Database Interaction:** In `mycred-transfer-object.php`, the `get_transfer()` method (Line 144) uses the ID to query the `$mycred_log_table` using a `LIKE` clause on the serialized `data` column (Line 163).\n\n### 4. Nonce Acquisition Strategy\nThe transfer actions are protected by a WordPress nonce, usually localized for the transfer form or history scripts.\n\n1.  **Identify Shortcode:** The transfer functionality is triggered by the `[mycred_transfer]` shortcode.\n2.  **Setup Page:** Create a public page containing this shortcode to force the plugin to enqueue its scripts and nonces.\n3.  **Extraction:**\n    *   Navigate to the page as the Subscriber user.\n    *   Use `browser_eval` to extract the nonce from the global JavaScript object `mycred_transfer` or similar.\n    *   **JS Variable:** `window.mycred_transfer?.nonce` (or `window.mycred_payout?.nonce` for payout-specific actions).\n    *   **Fallback:** If not in a global object, check `window.mycred?.nonce` which is a common catch-all in the plugin.\n\n### 5. Exploitation Strategy\nWe will demonstrate the vulnerability by having a Subscriber user \"payout\" (complete) a transfer they did not initiate.\n\n1.  **Preparation:** \n    *   Enable the \"Transfers\" add-on.\n    *   Generate a \"Pending\" or \"Incomplete\" transfer (often used in myCred for scheduled transfers or transfers requiring approval).\n2.  **Action:**\n    *   Obtain a valid `transfer_id`. Note that `generate_new_transfer_id` (Line 132) uses a predictable format: `'TXID' . timestamp . sender_id . recipient_id`.\n3.  **HTTP Request:**\n    ```http\n    POST \u002Fwp-admin\u002Fadmin-ajax.php HTTP\u002F1.1\n    Content-Type: application\u002Fx-www-form-urlencoded\n\n    action=mycred-payout-transfer&transfer_id=[TARGET_TXID]&_wpnonce=[EXTRACTED_NONCE]\n    ```\n4.  **Expected Response:** A JSON success message or a `1` (typical for successful WordPress AJAX).\n\n### 6. Test Data Setup\n1.  **Activate Add-on:**\n    `wp eval \"mycred_update_addon_settings('transfers', array('active' => true));\"` (or use the UI).\n2.  **Create Users:**\n    *   `Victim` (ID: 2)\n    *   `Attacker` (ID: 3, Subscriber role)\n3.  **Create Content:**\n    *   `wp post create --post_type=page --post_status=publish --post_title=\"Transfer\" --post_content='[mycred_transfer]'`\n4.  **Create Target Transfer:**\n    *   Manually insert or trigger a transfer with an \"incomplete\" or \"pending\" status from the Victim to another user. Record the `transfer_id`.\n\n### 7. Expected Results\n*   The AJAX request should return a success status code (200 OK) and a payload indicating the transfer was processed.\n*   The transfer entry in the myCred log table should change from `incomplete` to `completed`.\n*   The Attacker (Subscriber) should be able to trigger this for a transfer they were not involved in.\n\n### 8. Verification Steps\n1.  **Database Check:**\n    `wp db query \"SELECT * FROM wp_mycred_log WHERE data LIKE '%TXID...%'\" --format=yaml`\n    *Verify the `ref_id` or status in the `data` column has updated to reflect completion.*\n2.  **Balance Check:**\n    `wp mycred points get [Recipient_ID]`\n    *Verify that points were actually moved to the recipient after the unauthorized payout.*\n\n### 9. Alternative Approaches\n*   **Transfer Refund:** If `mycred-payout-transfer` is unavailable, attempt `mycred-refund-transfer`. This is even more critical as it would restore points to a sender's balance without authorization.\n*   **Direct Object Manipulation:** If the plugin uses a generic AJAX action like `mycred-action`, try passing `type=transfer&subaction=payout`.\n*   **Guessing IDs:** If no `transfer_id` is known, iterate through timestamps around the time a transfer was known to have occurred, as the `TXID` format is deterministic.","The myCred plugin for WordPress is vulnerable to unauthorized point transfers due to a missing capability check in the transfer object's request processing. Authenticated attackers with subscriber-level access can exploit this by overriding the sender ID in a transfer request, allowing them to move points from any user's account to themselves or others.","\u002F\u002F addons\u002Ftransfer\u002Fincludes\u002Fmycred-transfer-object.php line 632\n\n\u002F\u002F Sender\n$sender_id = get_current_user_id();\nif ( $this->request['user_id'] !== 'current' && absint( $this->request['user_id'] ) > 0 ) {\n    $sender_id = absint( $this->request['user_id'] );\n}\n$this->sender_id = $sender_id;","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fmycred\u002F3.0.3\u002Faddons\u002Ftransfer\u002Fincludes\u002Fmycred-transfer-object.php\t2025-09-18 11:05:44.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fmycred\u002F3.0.4\u002Faddons\u002Ftransfer\u002Fincludes\u002Fmycred-transfer-object.php\t2026-04-15 05:59:46.000000000 +0000\n@@ -632,7 +632,10 @@\n \t\t    \u002F\u002F Sender\n \t\t    $sender_id = get_current_user_id();\n \t\t    if ( $this->request['user_id'] !== 'current' && absint( $this->request['user_id'] ) > 0 ) {\n-\t\t        $sender_id = absint( $this->request['user_id'] );\n+\t\t        \u002F\u002F Patch: Restrict sender_id overrides to point administrators to prevent spoofing.\n+\t\t        if ( current_user_can( 'manage_options' ) || mycred()->user_is_point_admin() ) {\n+\t\t            $sender_id = absint( $this->request['user_id'] );\n+\t\t        }\n \t\t    }\n \t\t    $this->sender_id = $sender_id;","The exploit involves a subscriber-level user spoofing the sender of a point transfer. \n1. Enable the Transfers add-on in myCred settings.\n2. Obtain a valid WordPress nonce for myCred transfer actions, typically by visiting a page where the [mycred_transfer] shortcode is rendered.\n3. Send a POST request to wp-admin\u002Fadmin-ajax.php with the action for submitting a transfer (e.g., mycred-submit-transfer).\n4. Include the parameter 'user_id' in the request payload, setting it to the ID of the victim (the user from whom points should be deducted).\n5. Because versions \u003C= 3.0.3 do not check for administrative privileges before honoring the 'user_id' parameter, the plugin will process the transfer as if the victim initiated it, successfully deducting points from their account.","gemini-3-flash-preview","2026-05-04 18:29:36","2026-05-04 18:30:30",{"type":37,"vulnerable_version":38,"fixed_version":11,"vulnerable_browse":39,"vulnerable_zip":40,"fixed_browse":41,"fixed_zip":42,"all_tags":43},"plugin","3.0.3","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fmycred\u002Ftags\u002F3.0.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fmycred.3.0.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fmycred\u002Ftags\u002F3.0.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fmycred.3.0.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fmycred\u002Ftags"]