MyRewards <= 5.7.3 - Missing Authorization
Description
The MyRewards plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 5.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
What Changed in the Fix
Changes introduced in v5.7.4
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-40786 (MyRewards) ## 1. Vulnerability Summary The **MyRewards** plugin (up to 5.7.3) suffers from a **Missing Authorization** vulnerability within its administrative AJAX handling framework, `lws-adminpanel`. The plugin registers several AJAX actions via the …
Show full research plan
Exploitation Research Plan - CVE-2026-40786 (MyRewards)
1. Vulnerability Summary
The MyRewards plugin (up to 5.7.3) suffers from a Missing Authorization vulnerability within its administrative AJAX handling framework, lws-adminpanel. The plugin registers several AJAX actions via the wp_ajax_ hook, which makes them accessible to any authenticated user (including Subscribers). Specifically, the generic button trigger handler and point export actions fail to perform sufficient capability checks (e.g., current_user_can('manage_options')) before executing privileged loyalty system operations.
2. Attack Vector Analysis
- Endpoints:
/wp-admin/admin-ajax.php?action=woorewards-lite-export-wr/wp-admin/admin-ajax.php?action=woorewards-lite-export-points/wp-admin/admin-ajax.php?action=lws_adminpanel_field_button
- Vulnerable Action:
woorewards-lite-export-wr(Exporting loyalty pool data). - Required Parameter:
woorewards-lite_from_pool(The ID or slug of the loyalty pool to export). - Authentication: Authenticated, Subscriber-level or above.
- Preconditions: At least one Loyalty Pool must be configured in the
Summary
The MyRewards plugin for WordPress is vulnerable to unauthorized access and action execution due to missing capability and nonce checks in its internal administration framework (lws-adminpanel). Authenticated attackers, including those with subscriber-level permissions, can trigger administrative callbacks or export sensitive loyalty system data and points history.
Vulnerable Code
// assets/lws-adminpanel/include/internal/pages.php // In the constructor, the plugin registers a generic AJAX action for buttons if( $this->doingAjax ) { add_action('wp_ajax_lws_adminpanel_field_button', array($this, 'ajaxButton')); } --- // assets/lws-adminpanel/include/internal/pages.php (~line 481 in vulnerable version) // Inside the ajaxButton handler, it originally lacks nonce and capability checks before triggering callbacks $response = $this->trigAjaxButton($this->pages, $button, $data); --- // include/pointsflow/action.php // These actions lacked nonce verification, allowing unauthorized or cross-site triggered exports function exportWR() { if( !\current_user_can('manage_options') ) \wp_die('forbidden', 403); // ... export logic ... } function exportPoints() { if( !\current_user_can('manage_options') ) \wp_die('forbidden', 403); // ... export logic ... }
Security Fix
@@ -481,6 +481,11 @@ if( $data === null ) exit(0); + $nonce = sanitize_text_field(wp_unslash($data['lws_adminpanel_triggerable_button_nonce'] ?? '')); + if (!\wp_verify_nonce($nonce, 'lws_adminpanel_triggerable_button_nonce')) { + \wp_send_json_error(__("Token expired. Please reload the page and retry.", 'lws-adminpanel')); + } + $response = $this->trigAjaxButton($this->pages, $button, $data); if( !is_null($response) ) { @@ -495,6 +500,11 @@ { foreach( $tree as $node ) { + $rights = $node['rights'] ?? ''; + if ($rights && !\current_user_can($rights)) { + continue; + } + if( is_array($node) ) { if( isset($node['fields']) ) @@ -208,6 +208,9 @@ function exportWR() { + if (!\wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['lws_btn_nonce'] ?? '')), 'woorewards-lite' . '-export-wr')) { + \wp_die('forbidden', 403); + } if( !\current_user_can('manage_options') ) \wp_die('forbidden', 403); @@ -225,6 +228,9 @@ function exportPoints() { + if (!\wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['lws_btn_nonce'] ?? '')), 'woorewards-lite' . '-export-points')) { + \wp_die('forbidden', 403); + } if( !\current_user_can('manage_options') ) \wp_die('forbidden', 403);
Exploit Outline
To exploit this vulnerability, an authenticated attacker with Subscriber-level access or higher can bypass intended security restrictions by targeting the plugin's AJAX endpoints. The attacker can directly send a request to /wp-admin/admin-ajax.php using the generic 'lws_adminpanel_field_button' action or the specific 'woorewards-lite-export-wr' / 'woorewards-lite-export-points' actions. Because the vulnerable versions failed to verify nonces for these triggers and did not consistently enforce capability checks within the 'lws-adminpanel' framework during AJAX processing, the attacker can execute sensitive functions (callbacks) or export data (such as loyalty pool contents via the woorewards-lite_from_pool parameter) that should be restricted to administrators.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.