EventPrime – Events Calendar, Bookings and Tickets <= 4.3.2.1 - Unauthenticated PHP Object Injection
Description
The EventPrime – Events Calendar, Bookings and Tickets plugin for WordPress is vulnerable to PHP Object Injection in versions up to, and including, 4.3.2.1 via deserialization of untrusted input. This makes it possible for unauthenticated attackers to inject a PHP Object. No known POP chain is present in the vulnerable software. If a POP chain is present via an additional plugin or theme installed on the target system, it could allow the attacker to delete arbitrary files, retrieve sensitive data, or execute code.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:HTechnical Details
<=4.3.2.1What Changed in the Fix
Changes introduced in v4.3.2.2
Source Code
WordPress.org SVNThis vulnerability research plan focuses on identifying and exploiting an unauthenticated PHP Object Injection vulnerability in the **EventPrime** plugin. Based on the provided source code and vulnerability description, the flaw resides in the use of `maybe_unserialize()` on untrusted data. ### 1. …
Show full research plan
This vulnerability research plan focuses on identifying and exploiting an unauthenticated PHP Object Injection vulnerability in the EventPrime plugin. Based on the provided source code and vulnerability description, the flaw resides in the use of maybe_unserialize() on untrusted data.
1. Vulnerability Summary
The EventPrime plugin (up to 4.3.2.1) uses maybe_unserialize() on data that can be influenced by unauthenticated users. In WordPress, maybe_unserialize() calls the native PHP unserialize() function if it detects a serialized string. This leads to PHP Object Injection, allowing an attacker to instantiate arbitrary PHP objects if a suitable POP (Property Oriented Programming) chain exists in the environment (e.g., in other plugins or themes).
2. Attack Vector Analysis
- Target Endpoint:
admin-ajax.php - Vulnerable Action:
ep_cancel_current_booking_process(associated with thecancel_current_booking_processmethod inEventM_Ajax_Service). - Parameter:
event_id(used to fetch meta), or potentially a direct parameter in a related AJAX action likeep_get_event_detailsorep_get_calendar_events. - Preconditions:
- The plugin must have "Guest Bookings" or "Frontend Event Submission" enabled (standard for event plugins).
- A valid nonce for
event-registration-form-nonceis
Summary
The EventPrime plugin for WordPress is vulnerable to unauthenticated PHP Object Injection due to the use of maybe_unserialize() on metadata that can be influenced by users. This occurs when data is retrieved via get_post_meta() and subsequently passed to maybe_unserialize(), leading to 'double deserialization' if an attacker can inject a serialized string into the database.
Vulnerable Code
// includes/class-ep-ajax.php (approx line 1262) public function cancel_current_booking_process() { if( wp_verify_nonce( $_POST['security'], 'event-registration-form-nonce' ) ) { $event_id = absint( $_POST['event_id'] ); // ... $event_seat_data = get_post_meta( $event_id, 'em_seat_data', true ); if( ! empty( $event_seat_data ) ) { // ... $event_seat_data = maybe_unserialize( $event_seat_data ); --- // public/partials/themes/default/frontend-submission/organizers.php (line 11) $selected_organizer = isset($args->event) && !empty($args->event->em_organizer) ? maybe_unserialize($args->event->em_organizer): array();
Security Fix
@@ -1249,12 +1249,12 @@ } } - // organizer - $org = array(); - if( isset( $data['em_organizer'] ) && !empty( $data['em_organizer'] ) ) { - $org = $data['em_organizer']; - update_post_meta( $post_id, 'em_organizer', $org ); - } + // organizer + $org = array(); + if( isset( $data['em_organizer'] ) && !empty( $data['em_organizer'] ) ) { + $org = $ep_functions->ep_sanitize_term_id_list( $data['em_organizer'] ); + update_post_meta( $post_id, 'em_organizer', $org ); + } if( isset( $data['new_organizer'] ) && $data['new_organizer'] == 1 ) { $organizer_name = isset( $data['new_organizer_name'] ) ? sanitize_text_field($data['new_organizer_name']) : ''; if( ! empty( $organizer_name ) ) { @@ -1274,14 +1274,15 @@ if( isset( $data['em_organizer_websites'] ) && ! empty( $data['em_organizer_websites'] ) ) { $org_data->em_organizer_websites = array_map( 'esc_url_raw', (array) $data['em_organizer_websites'] ); } - $org_data->description = isset( $data['new_event_organizer_description'] ) ? wp_kses_post($data['new_event_organizer_description']) : ''; - $org_data->em_image_id = isset( $data['org_attachment_id'] ) ? $data['org_attachment_id'] : ''; - $org_data->em_social_links = isset( $data['em_social_links'] ) ? array_map( 'esc_url_raw', (array) $data['em_social_links'] ) : ''; - $org[] = $ep_functions->create_organizer( (array)$org_data ); - } - } - update_post_meta( $post_id, 'em_organizer', $org ); - } + $org_data->description = isset( $data['new_event_organizer_description'] ) ? wp_kses_post($data['new_event_organizer_description']) : ''; + $org_data->em_image_id = isset( $data['org_attachment_id'] ) ? $data['org_attachment_id'] : ''; + $org_data->em_social_links = isset( $data['em_social_links'] ) ? array_map( 'esc_url_raw', (array) $data['em_social_links'] ) : ''; + $org[] = $ep_functions->create_organizer( (array)$org_data ); + } + } + $org = $ep_functions->ep_sanitize_term_id_list( $org ); + update_post_meta( $post_id, 'em_organizer', $org ); + }
Exploit Outline
The exploit requires two stages: injection and triggering. 1. **Injection**: An attacker identifies an input that is saved to post meta without proper sanitization (such as `em_organizer` via frontend event submission or specific license settings). They provide a 'double-serialized' payload—a string which, when deserialized once by WordPress's internal `get_post_meta`, results in a string that is itself a valid serialized PHP object (e.g., 's:21:"O:15:"Other_POP_Chain":0:{}";'). 2. **Triggering**: The attacker makes a request to an endpoint that retrieves this meta and calls `maybe_unserialize()` on it. One such endpoint is the AJAX action `ep_cancel_current_booking_process` (accessible via `admin-ajax.php`). The attacker provides the target `event_id` and a valid `event-registration-form-nonce` (typically found in the frontend event page's source). Upon processing, the plugin deserializes the attacker's object, triggering the PHP destructor/wakeup methods if a suitable POP chain is available in the environment.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.