Five Star Restaurant Menu and Food Ordering <= 2.5.2 - Missing Authorization
Description
The Five Star Restaurant Menu and Food Ordering plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 2.5.2. 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:NTechnical Details
<=2.5.2What Changed in the Fix
Changes introduced in v2.5.3
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-54835 (Placeholder ID) ## 1. Vulnerability Summary The **Five Star Restaurant Menu and Food Ordering** plugin (versions <= 2.5.2) contains a **Missing Authorization** vulnerability. The vulnerability resides in the handling of order status updates, specifical…
Show full research plan
Exploitation Research Plan - CVE-2026-54835 (Placeholder ID)
1. Vulnerability Summary
The Five Star Restaurant Menu and Food Ordering plugin (versions <= 2.5.2) contains a Missing Authorization vulnerability. The vulnerability resides in the handling of order status updates, specifically within the Stripe payment completion logic or administrative order actions processed via admin_init.
Due to the lack of capability checks (current_user_can()) and insufficient nonce validation on specific AJAX handlers or initialization hooks, an unauthenticated attacker can manipulate the status of restaurant orders (e.g., marking a pending order as paid/received).
- Vulnerable File:
includes/class-order-payments.php(and potentiallyincludes/class-ajax.php) - Vulnerable Function:
stripe_sca_succeed(hooked towp_ajax_nopriv_fdm_stripe_payment_succeed) or anadmin_inithandler infdmAdminOrders. - CVSS Impact: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N (Low Integrity Impact).
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
fdm_stripe_payment_succeed - Authentication: None required (Targeting `wp
Summary
The Five Star Restaurant Menu and Food Ordering plugin is vulnerable to unauthorized order status manipulation due to insufficient verification in the Stripe payment completion handler. Unauthenticated attackers can mark pending orders as paid by sending a forged AJAX request that bypasses actual Stripe transaction validation.
Vulnerable Code
// includes/class-order-payments.php public function stripe_sca_succeed() { global $fdm_controller; if ( ! isset( $_POST['order_id'] ) ) { return; } $order = new fdmOrderItem(); $order->load( intval( $_POST['order_id'] ) ); if ( $this->valid_payment( $order ) ) { $order->post_status = 'fdm_order_received'; $order->payment_amount = $fdm_controller->settings->get_setting( 'ordering-currency' ) != 'JPY' ? intval( $_POST['payment_amount'] ) / 100 : intval( $_POST['payment_amount'] ); $order->receipt_id = sanitize_text_field( $_POST['payment_id'] ); // Not needed anymore unset( $order->stripe_payment_intent_id ); $order->save_order_post(); } die(); } --- // includes/class-order-payments.php public function valid_payment( $order ) { return sanitize_text_field( $_POST['payment_id'] ) == $order->stripe_payment_intent_id; }
Security Fix
@@ -358,9 +358,16 @@ $order->post_status = 'fdm_order_received'; - $order->payment_amount = $fdm_controller->settings->get_setting( 'ordering-currency' ) != 'JPY' ? intval( $_POST['payment_amount'] ) / 100 : intval( $_POST['payment_amount'] ); + // load the stripe libraries + require_once( FDM_PLUGIN_DIR . '/lib/stripe/init.php' ); - $order->receipt_id = sanitize_text_field( $_POST['payment_id'] ); + \Stripe\Stripe::setApiKey( $this->get_secret() ); + + $intent = \Stripe\PaymentIntent::retrieve( $order->stripe_payment_intent_id ); + + $order->payment_amount = $fdm_controller->settings->get_setting( 'ordering-currency' ) != 'JPY' ? $intent->amount / 100 : $intent->amount; + + $order->receipt_id = $intent->id; // Not needed anymore unset( $order->stripe_payment_intent_id ); @@ -394,13 +401,41 @@ } /** - * Validate the payment success request by verifing the payment_intent ID + * Validate the payment success request by verifying the payment_intent ID * * @return bool true on valid else false */ public function valid_payment( $order ) { + global $fdm_controller; + + if ( empty( $order->stripe_payment_intent_id ) ) { return false; } + + $posted_id = sanitize_text_field( $_POST['payment_id'] ?? '' ); + if ( $posted_id !== $order->stripe_payment_intent_id ) { return false; } + + try { + + // load the stripe libraries + require_once( FDM_PLUGIN_DIR . '/lib/stripe/init.php' ); + + \Stripe\Stripe::setApiKey( $this->get_secret() ); + + $intent = \Stripe\PaymentIntent::retrieve( $order->stripe_payment_intent_id ); + + $is_hold = $fdm_controller->settings->get_setting( 'fdm-stripe-hold' ); + $valid_status = $is_hold ? 'requires_capture' : 'succeeded'; + + return $intent->status === $valid_status; + } + catch ( Exception $ex ) { + + if ( defined('WP_DEBUG') && WP_DEBUG ) { + + error_log( sprintf( __( 'Five Star FDM Stripe valid_payment error: %s', 'food-and-drink-menu' ), $ex->getMessage() ) ); + } - return sanitize_text_field( $_POST['payment_id'] ) == $order->stripe_payment_intent_id; + return false; + } }
Exploit Outline
1. An attacker identifies a pending order ID (which can often be enumerated or obtained after a legitimate checkout attempt is halted). 2. The attacker identifies the `stripe_payment_intent_id` associated with that order. In many Stripe implementations, this ID is sent to the client-side to initialize the payment element. 3. The attacker crafts a POST request to `/wp-admin/admin-ajax.php` with the action `fdm_stripe_payment_succeed`. 4. The payload includes the target `order_id`, the matching `payment_id` (the intent ID), and a `payment_amount` (e.g., 0). 5. Because version 2.5.2 only checks if the `payment_id` in the POST request matches the `stripe_payment_intent_id` stored in the database, the check passes without communicating with Stripe. 6. The plugin updates the order post status to 'fdm_order_received', effectively marking the order as paid in the restaurant's system without any money being transferred.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.