CVE-2026-2230

Booking Calendar <= 10.14.14 - Insecure Direct Object Reference to Authenticated (Subscriber+) Arbitrary User Settings Modification

mediumAuthorization Bypass Through User-Controlled Key
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
10.14.15
Patched in
2d
Time to patch

Description

The Booking Calendar plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 10.14.14 via the handle_ajax_save function due to missing validation on a user controlled key. This makes it possible for authenticated attackers, with Subscriber-level access and above, and booking permissions granted by an Administrator, to modify other users' plugin settings, such as booking calendar display options, which can disrupt the booking calendar functionality for the targeted user.

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<=10.14.14
PublishedFebruary 17, 2026
Last updatedFebruary 18, 2026
Affected pluginbooking

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps to exploit **CVE-2026-2230**, an Insecure Direct Object Reference (IDOR) in the **Booking Calendar** plugin. ### 1. Vulnerability Summary The Booking Calendar plugin (up to version 10.14.14) contains an IDOR vulnerability in the `handle_ajax_save` function. The…

Show full research plan

This research plan outlines the steps to exploit CVE-2026-2230, an Insecure Direct Object Reference (IDOR) in the Booking Calendar plugin.

1. Vulnerability Summary

The Booking Calendar plugin (up to version 10.14.14) contains an IDOR vulnerability in the handle_ajax_save function. The function is designed to save user-specific plugin settings (like calendar display preferences) via AJAX. However, it fails to validate if the authenticated user has permission to modify settings for the specific user ID provided in the request. While it requires the attacker to have "booking permissions" (a setting configured by an administrator), once granted, a low-privileged user (Subscriber+) can modify the settings of any other user, including administrators.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: wpbc_ajax_save_settings (Inferred based on handle_ajax_save and plugin naming conventions).
  • Vulnerable Parameter: user_id or uid (The "user-controlled key" mentioned in the description).
  • Authentication: Authenticated (Subscriber-level or higher).
  • Precondition: The administrator must have enabled "Booking Permissions" for the attacker's role in the plugin settings (Settings > General > "User Permissions" or "Who can see the booking system").

3. Code Flow (Inferred)

  1. Entry Point: The plugin registers an AJAX action for wp_ajax_wpbc_ajax_save_settings (inferred) pointing to the handle_ajax_save method within a settings or AJAX handler class (likely in core/lib/wpbc-ajax.php or core/admin/wpbc-settings.php).
  2. Authorization Check: The function checks if the current user has the general capability to manage bookings (e.g., current_user_can( 'booking_user_role' )).
  3. Vulnerability: The function retrieves a user identifier from the request (e.g., $target_user_id = $_POST['user_id']).
  4. Sink: It proceeds to call update_user_meta( $target_user_id, 'booking_settings_key', ... ) without verifying if $target_user_id matches the current user's ID or if the current user has manage_options (admin) privileges.

4. Nonce Acquisition Strategy

The Booking Calendar plugin typically enqueues global JS variables for authenticated users permitted to use the system.

  1. Identify Trigger: The nonce and AJAX variables are usually enqueued on the "Bookings" management page or the "Settings" page.
  2. Access Page: Log in as the Subscriber and navigate to the plugin's dashboard area (e.g., /wp-admin/admin.php?page=wpbc).
  3. Extract Nonce: Use browser_eval to extract the nonce from the localized script object.
    • Inferred Variable: window.wpbc_global_vars
    • Inferred Key: nonce or ajax_nonce.
    • JS Command: browser_eval("window.wpbc_global_vars?.ajax_nonce")

5. Exploitation Strategy

The goal is to modify the settings of the Administrator (User ID 1) using the Subscriber's session.

Step 1: Discover Target Settings
Identify which settings keys are modified by handle_ajax_save. Common keys in this plugin relate to calendar view (e.g., booking_view_type, calendar_skin).

Step 2: Prepare the Payload

  • Method: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Body (URL-encoded):
    • action: wpbc_ajax_save_settings (verify via grep)
    • nonce: [EXTRACTED_NONCE]
    • user_id: 1 (The target Admin ID)
    • settings_data[view_mode]: malicious_value (or any setting that disrupts display)

Step 3: Execute via http_request

{
  "method": "POST",
  "url": "http://localhost:8080/wp-admin/admin-ajax.php",
  "headers": {
    "Content-Type": "application/x-www-form-urlencoded"
  },
  "body": "action=wpbc_ajax_save_settings&nonce=NONCE_VALUE&user_id=1&settings_data[calendar_view_mode]=month_only"
}

6. Test Data Setup

  1. Roles:
    • Admin user (admin).
    • Subscriber user (attacker).
  2. Plugin Configuration:
    • As Admin, go to Booking > Settings.
    • Find the "User Permissions" section.
    • Enable the Subscriber role to "View Bookings" or "Manage Settings". This grants the PR:L requirement mentioned in the CVSS.
  3. Target Metadata: Ensure the Admin user (ID 1) has some existing plugin settings that can be visibly modified.

7. Expected Results

  • The AJAX request should return a success status (e.g., {"status":"success"} or 1).
  • The user metadata for User ID 1 in the wp_usermeta table should be updated with the values provided by the Subscriber.
  • When the Admin logs in, their Booking Calendar view will be changed/disrupted.

8. Verification Steps

  1. Database Check: Use WP-CLI to inspect the Admin's user meta before and after the attack.
    • wp user meta get 1 wpbc_settings (The meta key name may vary; search wp_usermeta for keys containing wpbc).
  2. UI Verification: Log in as Admin and verify if the Booking Calendar dashboard reflects the changes made by the attacker.

9. Alternative Approaches

  • Blind Modification: If the specific meta key is unknown, grep the plugin source for update_user_meta calls within the handle_ajax_save function to find the exact key name.
  • Parameter Name Variation: The IDOR might use uid, user_id, or id. Verify the exact parameter name by inspecting the handle_ajax_save function source code:
    grep -rn "function handle_ajax_save" wp-content/plugins/booking/
    
  • Action Name Verification: Confirm the AJAX action name by searching for the add_action call:
    grep -rn "wp_ajax_.*handle_ajax_save" wp-content/plugins/booking/
    
Research Findings
Static analysis — not yet PoC-verified

Summary

The Booking Calendar plugin for WordPress is vulnerable to an Insecure Direct Object Reference (IDOR) via the handle_ajax_save function. This vulnerability allows authenticated users with subscriber-level access (provided they have been granted booking permissions by an administrator) to modify the plugin settings of any other user, including administrators, by supplying a target user ID in the request.

Vulnerable Code

// Inferred from research plan in core/lib/wpbc-ajax.php or similar settings handler
public function handle_ajax_save() {
    // Check if user has basic permission provided by admin
    if ( ! current_user_can( 'booking_user_role' ) ) {
        wp_die();
    }

    check_ajax_referer( 'wpbc_settings_nonce', 'nonce' );

    // VULNERABILITY: The function retrieves user_id from POST without validating ownership
    $user_id = isset( $_POST['user_id'] ) ? intval( $_POST['user_id'] ) : get_current_user_id();
    $settings = $_POST['settings_data'];

    // Update meta for the user-controlled ID
    update_user_meta( $user_id, 'booking_settings_key', $settings );

    wp_send_json_success();
}

Security Fix

--- wp-content/plugins/booking/core/lib/wpbc-ajax.php
+++ wp-content/plugins/booking/core/lib/wpbc-ajax.php
@@ -10,7 +10,12 @@
     check_ajax_referer( 'wpbc_settings_nonce', 'nonce' );
 
     $user_id = isset( $_POST['user_id'] ) ? intval( $_POST['user_id'] ) : get_current_user_id();
+
+    // Validate that the user is editing their own settings or is an administrator
+    if ( $user_id !== get_current_user_id() && ! current_user_can( 'manage_options' ) ) {
+        wp_send_json_error( array( 'message' => 'Unauthorized' ), 403 );
+        return;
+    }
+
     $settings = $_POST['settings_data'];
     update_user_meta( $user_id, 'booking_settings_key', $settings );

Exploit Outline

To exploit this vulnerability, an attacker first needs to be logged in as a Subscriber and have 'booking permissions' enabled for their role by an Administrator. The attacker identifies the AJAX action (e.g., wpbc_ajax_save_settings) and extracts the required security nonce from the global JavaScript variable 'wpbc_global_vars' on the plugin's dashboard page. The attacker then sends a POST request to admin-ajax.php containing the action, the nonce, a target user_id (such as 1 for the site administrator), and a settings_data array containing the desired configuration changes. Because the server fails to verify if the requester has authority over the provided user_id, it updates the target user's meta data, allowing the attacker to disrupt the administrator's calendar views or plugin functionality.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.