CVE-2026-54835

Five Star Restaurant Menu and Food Ordering <= 2.5.2 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
2.5.3
Patched in
6d
Time to patch

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: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.5.2
PublishedJune 18, 2026
Last updatedJune 23, 2026
Affected pluginfood-and-drink-menu

What Changed in the Fix

Changes introduced in v2.5.3

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# 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 potentially includes/class-ajax.php)
  • Vulnerable Function: stripe_sca_succeed (hooked to wp_ajax_nopriv_fdm_stripe_payment_succeed) or an admin_init handler in fdmAdminOrders.
  • 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
Research Findings
Static analysis — not yet PoC-verified

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

--- /home/deploy/wp-safety.org/data/plugin-versions/food-and-drink-menu/2.5.2/includes/class-order-payments.php	2025-04-29 21:40:20.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/food-and-drink-menu/2.5.3/includes/class-order-payments.php	2026-06-03 13:44:50.000000000 +0000
@@ -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.