[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fjE4zhzAnBP8qSie52mOoVXAfn-WROcWdA_e11kJKYtQ":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-25327","five-star-restaurant-reservations-wordpress-booking-plugin-missing-authorization","Five Star Restaurant Reservations – WordPress Booking Plugin \u003C= 2.7.9 - Missing Authorization","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.","restaurant-reservations",null,"\u003C=2.7.9","2.7.10","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-03-23 00:00:00","2026-04-02 15:18:23",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F1a657a1d-3b01-444c-af4e-c9ebebfbc01a?source=api-prod",11,[22,23,24,25,26,27,28,29],"assets\u002Fcss\u002Fbooking-form.css","assets\u002Fcss\u002Fcolumns-new.css","assets\u002Fjs\u002Fbooking-form.js","includes\u002FAjax.class.php","includes\u002FBooking.class.php","includes\u002FCron.class.php","includes\u002FNotification.class.php","includes\u002FSettings.class.php","researched",false,3,"# Exploitation Research Plan - CVE-2026-25327\n\n## 1. Vulnerability Summary\nThe **Five Star Restaurant Reservations** plugin (\u003C= 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.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Action:** `rtb_cancel_reservations` (unauthenticated)\n- **Parameters:**\n    - `action`: `rtb_cancel_reservations`\n    - `nonce`: A valid WordPress nonce for the `rtb-booking-form` action.\n    - `booking_id`: The ID (Post ID) of the target reservation.\n    - `booking_email`: The email address associated with the reservation.\n- **Authentication:** None (Unauthenticated).\n- **Preconditions:** The attacker must know the victim's email address and the specific `booking_id` (which is an incrementing integer).\n\n## 3. Code Flow\n1. **Entry Point:** The","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.","\u002F\u002F includes\u002FAjax.class.php lines 83-86 (v2.7.9)\nadd_action( 'wp_ajax_rtb_find_reservations', array( $this, 'get_reservations' ) );\nadd_action( 'wp_ajax_nopriv_rtb_find_reservations', array( $this, 'get_reservations' ) );\n\nadd_action( 'wp_ajax_rtb_cancel_reservations', array( $this, 'cancel_reservation' ), 10, 0 );\nadd_action( 'wp_ajax_nopriv_rtb_cancel_reservations', array( $this, 'cancel_reservation' ), 10, 0 );\n\n---\n\n\u002F\u002F includes\u002FAjax.class.php lines 161-177 (v2.7.9)\npublic function cancel_reservation( $ajax = true ) {\n\tglobal $rtb_controller;\n\n\tif ( $ajax && !check_ajax_referer( 'rtb-booking-form', 'nonce' ) ) {\n\t\trtbHelper::bad_nonce_ajax();\n\t}\n\n\t$cancelled_redirect = $rtb_controller->settings->get_setting( 'cancelled-redirect-page' );\n\n\t$booking_id = isset($_REQUEST['booking_id']) ? absint( $_REQUEST['booking_id'] ) : '';\n\t$booking_email = isset($_REQUEST['booking_email']) ? sanitize_email( $_REQUEST['booking_email'] ) : '';\n\n\t$success = false;\n\t$error = array(\n\t\t'error' => 'unknown',\n\t\t'msg' => __( 'Unkown error. Please try again', 'restaurant-reservations' )\n\t);\n\n\t$booking = new rtbBooking();\n\tif ( $booking->load_post( $booking_id ) ) {\n\t\tif ( $booking_email == $booking->email ) {\n\t\t\twp_update_post( array( 'ID' => $booking->ID, 'post_status' => 'cancelled' ) );\n\n\t\t\t$success = true;\n\t\t}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Frestaurant-reservations\u002F2.7.9\u002Fincludes\u002FAjax.class.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Frestaurant-reservations\u002F2.7.10\u002Fincludes\u002FAjax.class.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Frestaurant-reservations\u002F2.7.9\u002Fincludes\u002FAjax.class.php\t2025-07-30 18:57:06.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Frestaurant-reservations\u002F2.7.10\u002Fincludes\u002FAjax.class.php\t2026-02-02 22:42:50.000000000 +0000\n@@ -89,6 +89,7 @@\n \t\t\t}\n \n \t\t\t$email = isset($_POST['booking_email']) ? sanitize_email( $_POST['booking_email'] ) : '';\n+\t\t\t$code = isset($_POST['booking_code']) ? sanitize_text_field( $_POST['booking_code'] ) : '';\n \n \t\t\tif ( ! $email ) {\n \t\t\t\twp_send_json_error(\n@@ -99,6 +100,15 @@\n \t\t\t\t);\n \t\t\t}\n \n+\t\t\tif ( ! $code and empty( $rtb_controller->settings->get_setting( 'disable-cancellation-code-required' ) ) ) {\n+\t\t\t\twp_send_json_error(\n+\t\t\t\t\tarray(\n+\t\t\t\t\t\t'error' => 'nocode',\n+\t\t\t\t\t\t'msg' => __( 'The cancellation code you entered is not valid.', 'restaurant-reservations' ),\n+\t\t\t\t\t)\n+\t\t\t\t);\n+\t\t\t}\n+\n \t\t\t$booking_status_lbls = $rtb_controller->cpts->booking_statuses;\n \n \t\t\t$bookings = array();\n@@ -114,15 +124,18 @@\n \t\t\t\tif ( $booking->load_post( $booking_id->post_id ) ) {\n \t\t\t\t\t$booking_date = (new DateTime($booking->date, wp_timezone()))->format('U');\n \t\t\t\t\tif ( in_array($booking->post_status, ['pending', 'payment_pending', 'payment_failed', 'confirmed'] ) and time() \u003C $booking_date ) {\n-\t\t\t\t\t\t$bookings[] = array(\n-\t\t\t\t\t\t\t'ID'         => $booking->ID,\n-\t\t\t\t\t\t\t'email'      => $booking->email,\n-\t\t\t\t\t\t\t'datetime'   => $booking->format_date( $booking->date ),\n-\t\t\t\t\t\t\t'datetime_u' => $booking_date,\n-\t\t\t\t\t\t\t'party'      => $booking->party,\n-\t\t\t\t\t\t\t'status'     => $booking->post_status,\n-\t\t\t\t\t\t\t'status_lbl' => $booking_status_lbls[$booking->post_status]['label']\n-\t\t\t\t\t\t);\n+\t\t\t\t\t\tif ( $booking->cancellation_code == $code or ! empty( $rtb_controller->settings->get_setting( 'disable-cancellation-code-required' ) ) ) {\n+\t\t\t\t\t\t\t$bookings[] = array(\n+\t\t\t\t\t\t\t\t'ID'         => $booking->ID,\n+\t\t\t\t\t\t\t\t'email'      => $booking->email,\n+\t\t\t\t\t\t\t\t'code'       => $booking->cancellation_code,\n+\t\t\t\t\t\t\t\t'datetime'   => $booking->format_date( $booking->date ),\n+\t\t\t\t\t\t\t\t'datetime_u' => $booking_date,\n+\t\t\t\t\t\t\t\t'party'      => $booking->party,\n+\t\t\t\t\t\t\t\t'status'     => $booking->post_status,\n+\t\t\t\t\t\t\t\t'status_lbl' => $booking_status_lbls[$booking->post_status]['label']\n+\t\t\t\t\t\t\t);\n+\t\t\t\t\t\t}\n \t\t\t\t\t}\n \t\t\t\t}\n \t\t\t}\n@@ -161,6 +174,7 @@\n \n \t\t\t$booking_id = isset($_REQUEST['booking_id']) ? absint( $_REQUEST['booking_id'] ) : '';\n \t\t\t$booking_email = isset($_REQUEST['booking_email']) ? sanitize_email( $_REQUEST['booking_email'] ) : '';\n+\t\t\t$booking_code = isset($_REQUEST['booking_code']) ? sanitize_text_field( $_REQUEST['booking_code'] ) : '';\n \n \t\t\t$success = false;\n \t\t\t$error = array(\n@@ -170,10 +184,22 @@\n \n \t\t\t$booking = new rtbBooking();\n \t\t\tif ( $booking->load_post( $booking_id ) ) {\n+\t\t\t\t\n \t\t\t\tif ( $booking_email == $booking->email ) {\n-\t\t\t\t\twp_update_post( array( 'ID' => $booking->ID, 'post_status' => 'cancelled' ) );\n+\t\t\t\t\t\n+\t\t\t\t\tif ( $booking_code != $booking->cancellation_code and empty( $rtb_controller->settings->get_setting( 'disable-cancellation-code-required' ) ) ) {\n+\t\t\t\t\t\t\n+\t\t\t\t\t\t$error = array(\n+\t\t\t\t\t\t\t'error' => 'invalidcode',\n+\t\t\t\t\t\t\t'msg' => __( 'The cancellation code you entered is not valid.', 'restaurant-reservations' ),\n+\t\t\t\t\t\t);\n+\t\t\t\t\t}\n+\t\t\t\t\telse {\n+\n+\t\t\t\t\t\twp_update_post( array( 'ID' => $booking->ID, 'post_status' => 'cancelled' ) );\n \n-\t\t\t\t\t$success = true;\n+\t\t\t\t\t\t$success = true;\n+\t\t\t\t\t}\n \t\t\t\t}\n \t\t\t\telse {\n \t\t\t\t\t$error = array(","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.\n2. **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.\n3. **Prepare Payload**: Construct an unauthenticated AJAX request targeting `wp-admin\u002Fadmin-ajax.php` with the following POST parameters:\n    - `action`: `rtb_cancel_reservations`\n    - `nonce`: [Extracted Nonce]\n    - `booking_id`: [Target Post ID]\n    - `booking_email`: [Associated Email]\n4. **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.","gemini-3-flash-preview","2026-04-17 23:53:50","2026-04-17 23:54:38",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","2.7.9","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Frestaurant-reservations\u002Ftags\u002F2.7.9","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Frestaurant-reservations.2.7.9.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Frestaurant-reservations\u002Ftags\u002F2.7.10","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Frestaurant-reservations.2.7.10.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Frestaurant-reservations\u002Ftags"]