CVE-2026-25327

Five Star Restaurant Reservations – WordPress Booking Plugin <= 2.7.9 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
2.7.10
Patched in
11d
Time to patch

Description

The Five Star Restaurant Reservations – WordPress Booking Plugin 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.7.9. This makes it possible for unauthenticated attackers to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.7.9
PublishedMarch 23, 2026
Last updatedApril 2, 2026

What Changed in the Fix

Changes introduced in v2.7.10

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-25327 ## 1. Vulnerability Summary The **Five Star Restaurant Reservations** plugin (<= 2.7.9) is vulnerable to **Missing Authorization** in its AJAX handlers. Specifically, several sensitive actions are registered via `wp_ajax_nopriv_` (unauthenticated) witho…

Show full research plan

Exploitation Research Plan - CVE-2026-25327

1. Vulnerability Summary

The Five Star Restaurant Reservations plugin (<= 2.7.9) is vulnerable to Missing Authorization in its AJAX handlers. Specifically, several sensitive actions are registered via wp_ajax_nopriv_ (unauthenticated) without sufficient validation that the requester is authorized to perform the action on a specific booking. While the plugin implements a nonce check and an email-matching check for functions like cancel_reservation, the reliance on a publicly available email address and a discoverable booking_id as the only authorization tokens constitutes "Missing Authorization" (or weak authorization) for unauthenticated users.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: rtb_cancel_reservations (unauthenticated)
  • Parameters:
    • action: rtb_cancel_reservations
    • nonce: A valid WordPress nonce for the rtb-booking-form action.
    • booking_id: The ID (Post ID) of the target reservation.
    • booking_email: The email address associated with the reservation.
  • Authentication: None (Unauthenticated).
  • Preconditions: The attacker must know the victim's email address and the specific booking_id (which is an incrementing integer).

3. Code Flow

  1. Entry Point: The
Research Findings
Static analysis — not yet PoC-verified

Summary

The Five Star Restaurant Reservations plugin for WordPress is vulnerable to unauthorized reservation cancellation in versions up to 2.7.9. This occurs because the AJAX handlers for finding and cancelling bookings rely solely on a sequential booking ID and the customer's email address for verification. Unauthenticated attackers can exploit this to find or cancel active reservations without a unique secret or proper authorization check.

Vulnerable Code

// includes/Ajax.class.php lines 83-86 (v2.7.9)
add_action( 'wp_ajax_rtb_find_reservations', array( $this, 'get_reservations' ) );
add_action( 'wp_ajax_nopriv_rtb_find_reservations', array( $this, 'get_reservations' ) );

add_action( 'wp_ajax_rtb_cancel_reservations', array( $this, 'cancel_reservation' ), 10, 0 );
add_action( 'wp_ajax_nopriv_rtb_cancel_reservations', array( $this, 'cancel_reservation' ), 10, 0 );

---

// includes/Ajax.class.php lines 161-177 (v2.7.9)
public function cancel_reservation( $ajax = true ) {
	global $rtb_controller;

	if ( $ajax && !check_ajax_referer( 'rtb-booking-form', 'nonce' ) ) {
		rtbHelper::bad_nonce_ajax();
	}

	$cancelled_redirect = $rtb_controller->settings->get_setting( 'cancelled-redirect-page' );

	$booking_id = isset($_REQUEST['booking_id']) ? absint( $_REQUEST['booking_id'] ) : '';
	$booking_email = isset($_REQUEST['booking_email']) ? sanitize_email( $_REQUEST['booking_email'] ) : '';

	$success = false;
	$error = array(
		'error' => 'unknown',
		'msg' => __( 'Unkown error. Please try again', 'restaurant-reservations' )
	);

	$booking = new rtbBooking();
	if ( $booking->load_post( $booking_id ) ) {
		if ( $booking_email == $booking->email ) {
			wp_update_post( array( 'ID' => $booking->ID, 'post_status' => 'cancelled' ) );

			$success = true;
		}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/restaurant-reservations/2.7.9/includes/Ajax.class.php /home/deploy/wp-safety.org/data/plugin-versions/restaurant-reservations/2.7.10/includes/Ajax.class.php
--- /home/deploy/wp-safety.org/data/plugin-versions/restaurant-reservations/2.7.9/includes/Ajax.class.php	2025-07-30 18:57:06.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/restaurant-reservations/2.7.10/includes/Ajax.class.php	2026-02-02 22:42:50.000000000 +0000
@@ -89,6 +89,7 @@
 			}
 
 			$email = isset($_POST['booking_email']) ? sanitize_email( $_POST['booking_email'] ) : '';
+			$code = isset($_POST['booking_code']) ? sanitize_text_field( $_POST['booking_code'] ) : '';
 
 			if ( ! $email ) {
 				wp_send_json_error(
@@ -99,6 +100,15 @@
 				);
 			}
 
+			if ( ! $code and empty( $rtb_controller->settings->get_setting( 'disable-cancellation-code-required' ) ) ) {
+				wp_send_json_error(
+					array(
+						'error' => 'nocode',
+						'msg' => __( 'The cancellation code you entered is not valid.', 'restaurant-reservations' ),
+					)
+				);
+			}
+
 			$booking_status_lbls = $rtb_controller->cpts->booking_statuses;
 
 			$bookings = array();
@@ -114,15 +124,18 @@
 				if ( $booking->load_post( $booking_id->post_id ) ) {
 					$booking_date = (new DateTime($booking->date, wp_timezone()))->format('U');
 					if ( in_array($booking->post_status, ['pending', 'payment_pending', 'payment_failed', 'confirmed'] ) and time() < $booking_date ) {
-						$bookings[] = array(
-							'ID'         => $booking->ID,
-							'email'      => $booking->email,
-							'datetime'   => $booking->format_date( $booking->date ),
-							'datetime_u' => $booking_date,
-							'party'      => $booking->party,
-							'status'     => $booking->post_status,
-							'status_lbl' => $booking_status_lbls[$booking->post_status]['label']
-						);
+						if ( $booking->cancellation_code == $code or ! empty( $rtb_controller->settings->get_setting( 'disable-cancellation-code-required' ) ) ) {
+							$bookings[] = array(
+								'ID'         => $booking->ID,
+								'email'      => $booking->email,
+								'code'       => $booking->cancellation_code,
+								'datetime'   => $booking->format_date( $booking->date ),
+								'datetime_u' => $booking_date,
+								'party'      => $booking->party,
+								'status'     => $booking->post_status,
+								'status_lbl' => $booking_status_lbls[$booking->post_status]['label']
+							);
+						}
 					}
 				}
 			}
@@ -161,6 +174,7 @@
 
 			$booking_id = isset($_REQUEST['booking_id']) ? absint( $_REQUEST['booking_id'] ) : '';
 			$booking_email = isset($_REQUEST['booking_email']) ? sanitize_email( $_REQUEST['booking_email'] ) : '';
+			$booking_code = isset($_REQUEST['booking_code']) ? sanitize_text_field( $_REQUEST['booking_code'] ) : '';
 
 			$success = false;
 			$error = array(
@@ -170,10 +184,22 @@
 
 			$booking = new rtbBooking();
 			if ( $booking->load_post( $booking_id ) ) {
+				
 				if ( $booking_email == $booking->email ) {
-					wp_update_post( array( 'ID' => $booking->ID, 'post_status' => 'cancelled' ) );
+					
+					if ( $booking_code != $booking->cancellation_code and empty( $rtb_controller->settings->get_setting( 'disable-cancellation-code-required' ) ) ) {
+						
+						$error = array(
+							'error' => 'invalidcode',
+							'msg' => __( 'The cancellation code you entered is not valid.', 'restaurant-reservations' ),
+						);
+					}
+					else {
+
+						wp_update_post( array( 'ID' => $booking->ID, 'post_status' => 'cancelled' ) );
 
-					$success = true;
+						$success = true;
+					}
 				}
 				else {
 					$error = array(

Exploit Outline

1. **Identify Target Data**: Obtain the Post ID (`booking_id`) of a target reservation and the associated customer email (`booking_email`). Booking IDs are sequential, making them vulnerable to enumeration. 2. **Obtain Nonce**: Access the frontend booking page and extract a valid WordPress nonce for the `rtb-booking-form` action from the JavaScript localization object or form fields. 3. **Prepare Payload**: Construct an unauthenticated AJAX request targeting `wp-admin/admin-ajax.php` with the following POST parameters: - `action`: `rtb_cancel_reservations` - `nonce`: [Extracted Nonce] - `booking_id`: [Target Post ID] - `booking_email`: [Associated Email] 4. **Trigger Cancellation**: Submit the request. The server-side logic will verify the email matches the ID in the database and, if successful, update the reservation status to 'cancelled' without requiring any secret token or user authentication.

Check if your site is affected.

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