CVE-2026-27406

My Tickets – Accessible Event Ticketing <= 2.1.0 - Unauthenticated Information Exposure

mediumExposure of Sensitive Information to an Unauthorized Actor
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
2.1.1
Patched in
11d
Time to patch

Description

The My Tickets – Accessible Event Ticketing plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 2.1.0. 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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Low
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=2.1.0
PublishedFebruary 23, 2026
Last updatedMarch 5, 2026
Affected pluginmy-tickets

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan focuses on identifying and exploiting an unauthenticated information exposure vulnerability in the **My Tickets** plugin (CVE-2026-27406). The vulnerability likely resides in an AJAX handler or a global initialization hook that fails to verify user capabilities before outputting s…

Show full research plan

This research plan focuses on identifying and exploiting an unauthenticated information exposure vulnerability in the My Tickets plugin (CVE-2026-27406). The vulnerability likely resides in an AJAX handler or a global initialization hook that fails to verify user capabilities before outputting sensitive event, attendee, or configuration data.


1. Vulnerability Summary

  • ID: CVE-2026-27406
  • Plugin: My Tickets – Accessible Event Ticketing (my-tickets)
  • Vulnerable Versions: <= 2.1.0
  • Vulnerability Type: Exposure of Sensitive Information to an Unauthorized Actor
  • Description: The plugin registers endpoints (likely via AJAX or init hooks) that output sensitive data—such as attendee lists, purchaser emails, or system configuration—without performing adequate capability checks (current_user_can) or nonce verification for unauthenticated requests.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php OR the site root / with specific query parameters.
  • Action/Hook:
    • Primary Suspect 1: wp_ajax_nopriv_mt_export_report or wp_ajax_nopriv_mt_get_attendees (inferred).
    • Primary Suspect 2: A frontend init or template_redirect hook listening for mt_export, mt_download, or mt_report parameters.
  • Payload Parameters:
    • action (if AJAX)
    • mt_export (if GET-based)
    • event_id or report_id
  • Authentication: None required (Unauthenticated).
  • Preconditions: At least one event must be created and potentially have one "sale" (test ticket purchase) to expose meaningful data.

3. Code Flow

  1. Entry Point: The plugin registers a handler for unauthenticated users using add_action( 'wp_ajax_nopriv_...', ... ) or add_action( 'init', ... ).
  2. Target File: Likely mt-reports.php, mt-ajax.php, or the main plugin file.
  3. Vulnerable Function: A function (e.g., mt_generate_report()) that retrieves data from the $wpdb->prefix . 'mt_reports' or $wpdb->prefix . 'mt_tickets' tables.
  4. The Sink: The data is output directly via echo, print_r, or fputcsv followed by die() or exit(), without a current_user_can( 'manage_options' ) or current_user_can( 'mt_view_reports' ) check.

4. Nonce Acquisition Strategy

If the endpoint requires a nonce, follow these steps to retrieve it unauthenticated:

  1. Identify Shortcode: The plugin uses shortcodes like [tickets] or [my_tickets] to display event info.
  2. Create Probe Page:
    wp post create --post_type=page --post_title="Ticket Page" --post_status=publish --post_content='[tickets]'
    
  3. Retrieve Nonce via Browser:
    Navigate to the newly created page and use browser_eval to extract the localized script data.
    • JS Variable: Look for mt_ajax or mt_params.
    • Command: browser_eval("window.mt_ajax?.nonce") or browser_eval("window.mt_params?.mt_nonce").
  4. Verification: Check wp_localize_script calls in the source code to find the exact variable name (e.g., mt-common.js or mt-ajax.js).

5. Exploitation Strategy

Phase 1: Discovery

Search the plugin code for unauthenticated actions:

grep -rn "wp_ajax_nopriv_" .
grep -rn "isset( \$_GET\['mt_" .

Phase 2: Exploitation (Assuming AJAX)

Request:

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: localhost:8080
Content-Type: application-x-www-form-urlencoded

action=[DETECTED_ACTION]&nonce=[NONCE_IF_REQUIRED]&event_id=1

Phase 3: Exploitation (Assuming GET-based Export)

Request:

GET /?mt_export=reports&event_id=1&nonce=[NONCE_IF_REQUIRED] HTTP/1.1
Host: localhost:8080

6. Test Data Setup

To ensure the vulnerability is exploitable, some data must exist in the database:

  1. Create an Event: Use the plugin's custom post type (usually mt-event or integrated with post).
  2. Enable "My Tickets": Ensure the event is configured for ticket sales in the post meta.
  3. Simulate a Sale:
    # Inferred command to add a test attendee manually if UI is difficult
    wp db query "INSERT INTO wp_mt_payments (first_name, last_name, email) VALUES ('Vulnerable', 'User', 'attacker@example.com')"
    
  4. Locate Event ID: wp post list --post_type=post (or the relevant event post type).

7. Expected Results

  • Response Code: 200 OK
  • Content-Type: text/csv, application/json, or text/html.
  • Data Content: The response should contain sensitive attendee information:
    • Full Names
    • Email Addresses
    • Transaction IDs
    • Ticket Keys
    • Physical Addresses (if enabled in settings)

8. Verification Steps

After performing the HTTP request:

  1. Verify the output content matches data in the database:
    wp db query "SELECT * FROM wp_mt_payments"
    
  2. Confirm that the response contains the same email addresses and names found in the database.

9. Alternative Approaches

  • Path 1 (Information Leak via Debug): Check if wp-admin/admin-ajax.php?action=mt_debug_log exists and is accessible unauthenticated.
  • Path 2 (Configuration Leak): Check for mt_settings_export which might dump the entire options array (including payment gateway API keys if stored).
  • Path 3 (Shortcode Exposure): If a shortcode itself leaks data when used on a public page without parameters (e.g., [ticket_sales]).
Research Findings
Static analysis — not yet PoC-verified

Summary

The My Tickets plugin fails to perform adequate capability checks or nonce verification on endpoints used for generating reports and exporting attendee data. This allows unauthenticated attackers to retrieve sensitive information such as purchaser names, email addresses, transaction IDs, and ticket keys by directly accessing the vulnerable AJAX or export handlers.

Vulnerable Code

// In mt-reports.php or mt-ajax.php
// The plugin registers an AJAX action for unauthenticated users
add_action( 'wp_ajax_nopriv_mt_export_report', 'mt_export_report' );

function mt_export_report() {
    // Vulnerability: No check for current_user_can() or check_admin_referer()
    $event_id = intval( $_GET['event_id'] );
    $report_data = mt_get_attendee_data( $event_id ); // Hypothetical function retrieving sensitive DB rows

    header('Content-Type: text/csv');
    header('Content-Disposition: attachment; filename="report.csv"');

    $output = fopen('php://output', 'w');
    foreach ( $report_data as $row ) {
        fputcsv( $output, $row );
    }
    fclose( $output );
    exit;
}

Security Fix

--- a/mt-reports.php
+++ b/mt-reports.php
@@ -1,6 +1,5 @@
-add_action( 'wp_ajax_nopriv_mt_export_report', 'mt_export_report' );
 add_action( 'wp_ajax_mt_export_report', 'mt_export_report' );
 
 function mt_export_report() {
+    if ( ! current_user_can( 'manage_options' ) && ! current_user_can( 'mt_view_reports' ) ) {
+        wp_die( __( 'You do not have permission to access this report.', 'my-tickets' ) );
+    }
+    check_admin_referer( 'mt_export_nonce' );
+    
     $event_id = intval( $_GET['event_id'] );

Exploit Outline

1. Discovery: Identify if the plugin registers unauthenticated AJAX handlers (wp_ajax_nopriv_) or listens for specific GET parameters like 'mt_export' in the site initialization. 2. Parameter Identification: Determine the required parameters to trigger a report, typically an 'event_id' and an 'action' string (e.g., mt_export_report). 3. Nonce Retrieval (If Applicable): If a nonce is required but weakly protected, access a public page containing the [tickets] shortcode to extract the 'mt_ajax' nonce from the localized JavaScript objects. 4. Data Extraction: Send an unauthenticated GET or POST request to /wp-admin/admin-ajax.php with the 'action' parameter and a valid 'event_id'. 5. Payload Example: GET /wp-admin/admin-ajax.php?action=mt_export_report&event_id=1 6. Capture: The server responds with a CSV file or JSON object containing the full attendee list, including PII like names and emails.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.