Eventin – Events Calendar, Event Booking, Ticket & Registration (AI Powered) <= 4.1.8 Missing Authorization to Authenticated (Subscriber+) Order Information Exposure
Description
The Eventin – Events Calendar, Event Booking, Ticket & Registration (AI Powered) plugin for WordPress is vulnerable to unauthorized access of data due to a improper capability check on the get_item_permissions_check() function in all versions up to, and including, 4.1.8. This makes it possible for authenticated attackers, with Subscriber-level access and above, to read arbitrary order data including customer PII (name, email, phone) by iterating order IDs.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=4.1.8What Changed in the Fix
Changes introduced in v4.1.9
Source Code
WordPress.org SVN# Vulnerability Research Plan: CVE-2026-4109 - Eventin Order Information Exposure ## 1. Vulnerability Summary The **Eventin** plugin (versions <= 4.1.8) contains a **Missing Authorization** vulnerability within its REST API implementation. Specifically, the `get_item_permissions_check()` function (…
Show full research plan
Vulnerability Research Plan: CVE-2026-4109 - Eventin Order Information Exposure
1. Vulnerability Summary
The Eventin plugin (versions <= 4.1.8) contains a Missing Authorization vulnerability within its REST API implementation. Specifically, the get_item_permissions_check() function (likely within a class extending WP_REST_Controller for orders or attendees) fails to properly restrict access to order data. This allows any authenticated user, including those with the Subscriber role, to retrieve sensitive order details—including Customer PII (Name, Email, Phone)—by directly querying the REST API and iterating through Order IDs.
2. Attack Vector Analysis
- Endpoint: WordPress REST API.
- Likely Route:
/wp-json/eventin/v1/orders/(?P<id>[\d]+)or/wp-json/eventin/v1/attendees/(?P<id>[\d]+)(Namespace:eventin/v1inferred from standard plugin architecture). - HTTP Method:
GET. - Authentication: Authenticated (Subscriber level or higher).
- Payload: Path parameter containing the target
order_id. - Preconditions: At least one order/booking must exist in the system for data to be exposed.
3. Code Flow
- Registration: The plugin registers REST routes during the
rest_api_inithook. One of these routes handles order retrieval. - Request Initiation: A Subscriber user sends a
GETrequest to/wp-json/eventin/v1/orders/<ID>. - Permission Check: The WordPress REST API calls the
permission_callbackdefined for that route. In this plugin, it points toget_item_permissions_check(). - Vulnerable Logic: Inside
get_item_permissions_check(), the code likely checks for a generic capability likereador simply verifiesis_user_logged_in(), rather than checking if the user is an admin or if the order belongs specifically to the requesting user. - Information Disclosure: Because the check passes for Subscribers, the controller proceeds to
get_item(), fetches the order data (which includes PII), and returns it in the JSON response.
4. Nonce Acquisition Strategy
The WordPress REST API requires a _wpnonce parameter or X-WP-Nonce header for authenticated requests to prevent CSRF, even for some GET requests if the session is cookie-based.
- Identify Trigger: The
base/Enqueue/admin.phpfile enqueues several scripts likeetn-app-indexandetn-dashboard. These typically load the WordPress REST environment. - Create Page: A Subscriber user can access the standard WordPress dashboard (
/wp-admin/index.php). - Execute Extraction:
- Navigate to
/wp-admin/index.phpas the Subscriber. - The REST nonce is globally available in the
wpApiSettingsobject on most admin pages or can be extracted from the localized data of the plugin's scripts. - JS Command:
browser_eval("wpApiSettings.nonce")orbrowser_eval("localized_data_obj.nonce")(based onetn_get_locale_data()seen inbase/Enqueue/admin.php).
- Navigate to
- Action String: The nonce action used for the REST API is always
wp_rest.
5. Exploitation Strategy
- Preparation: Log in as a Subscriber user.
- Nonce Retrieval: Use
browser_evalto get thewp_restnonce. - Discovery: Identify the REST namespace.
- Request
GET /wp-json/and look for namespaces containing "eventin".
- Request
- Targeting: Access the order endpoint.
- Request Method:
GET - URL:
http://localhost:8080/wp-json/eventin/v1/orders/1(Increment IDs to find data). - Headers:
X-WP-Nonce: [EXTRACTED_NONCE]Cookie: [SUBSCRIBER_COOKIES]
- Request Method:
- Iteration: Use a script or loop to iterate IDs from 1 to 100.
6. Test Data Setup
To demonstrate the PII exposure, the environment must contain an order:
- Install Eventin: Ensure the plugin (v4.1.8) is active.
- Create Event: Use WP-CLI to create an event post type.
wp post create --post_type=etn-event --post_title="Sensitive Event" --post_status=publish
- Create Order: As Admin, create a manual booking/order or use the front-end to book a ticket for a dummy user "Victim User" with email
victim@example.comand phone555-0199. - Create Attacker: Create a user with the Subscriber role.
wp user create attacker attacker@example.com --role=subscriber --user_pass=password123
7. Expected Results
- Successful Exploit: The server returns a
200 OKresponse with a JSON body containing fields likecustomer_name,customer_email,customer_phone, andorder_totalfor an order ID that does not belong to the Subscriber. - Vulnerable Response Snippet:
{ "id": 1, "order_details": { "full_name": "Victim User", "email": "victim@example.com", "phone": "555-0199" } }
8. Verification Steps
- HTTP Check: Confirm the response code is
200and the PII is present in the JSON output. - Database Correlation: Verify the returned data matches the entries in the
wp_posts(post_typeetn-orderor similar) andwp_postmetatables.wp db query "SELECT * FROM wp_postmeta WHERE post_id = 1"
- Capability Check: Confirm the "attacker" user indeed only has the
subscriberrole and should not normally see other users' orders.wp user get attacker --field=roles
9. Alternative Approaches
- Alternative Endpoints: If
/orders/is not the route, check/attendees/or/tickets/. The core issue is theget_item_permissions_checkin the controller handling any booking-related data. - Export Functionality: Check if the CSV/JSON exporters defined in
base/Exporter/are reachable via an unprivileged AJAX or REST action. The description specifically mentionsget_item_permissions_check(), which is strongly associated with the REST API. - Public REST: Check if the endpoint allows access even without a nonce (though authenticated) if the
permission_callbackreturnstrue.
Summary
The Eventin plugin for WordPress (versions up to 4.1.8) fails to perform adequate authorization checks within its REST API controller for order retrieval. This flaw allows authenticated users, including those with Subscriber-level roles, to access sensitive customer PII such as names, email addresses, and phone numbers by iterating through order IDs via the API.
Security Fix
@@ -134,7 +134,7 @@ wp_localize_script( 'etn-onboard-index', 'localized_data_obj', $localize_data ); wp_enqueue_style( 'etn-icon' ); // Enque block editor style in events create and edit pages only - if ( isset( $_GET['page'] ) && $_GET['page'] === 'eventin' ) { + if ( isset( $_GET['page'] ) && $_GET['page'] === 'eventin' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- admin script enqueue condition; page param compared to a literal string only. wp_enqueue_style( 'wp-block-editor' ); } } @@ -194,7 +194,7 @@ } // Parse the URL - $url_parts = parse_url( $url ); + $url_parts = wp_parse_url( $url ); // Check if the URL has a path component if ( ! isset( $url_parts['path'] ) ) { @@ -204,7 +204,7 @@ $clean_path = str_replace( '.js', '.asset.php', $url_parts['path'] ); // Get the file path from the URL path - $file_path = $_SERVER['DOCUMENT_ROOT'] . $clean_path; + $file_path = ( isset( $_SERVER['DOCUMENT_ROOT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['DOCUMENT_ROOT'] ) ) : '' ) . $clean_path; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- DOCUMENT_ROOT is a trusted server variable used only to build a file path, not output or stored. // Check if the file exists if ( ! file_exists( $file_path ) ) {
Exploit Outline
1. Log in to the WordPress site as an authenticated user (e.g., Subscriber role). 2. Obtain a valid REST API nonce from the WordPress dashboard, typically available in the 'wpApiSettings.nonce' JavaScript object. 3. Identify a target order ID by observing existing bookings or guessing a numerical sequence. 4. Send an authenticated GET request to the Eventin REST API endpoint: '/wp-json/eventin/v1/orders/<ID>', passing the nonce in the 'X-WP-Nonce' header. 5. The API will respond with a JSON object containing sensitive PII for the order, including full_name, email, and phone, regardless of whether the order belongs to the requesting user. 6. Automate this process by iterating through numerical IDs to extract a full database of customer information.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.