CVE-2026-32492

My Tickets – Accessible Event Ticketing <= 2.1.1 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
2.1.2
Patched in
8d
Time to patch

Description

The My Tickets – Accessible Event Ticketing plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 2.1.1. This makes it possible for unauthenticated attackers to perform an unauthorized action.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=2.1.1
PublishedMarch 20, 2026
Last updatedMarch 27, 2026
Affected pluginmy-tickets

What Changed in the Fix

Changes introduced in v2.1.2

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2026-32492 Missing Authorization in My Tickets ## 1. Vulnerability Summary The **My Tickets** plugin for WordPress (versions <= 2.1.1) is vulnerable to **Missing Authorization** in its AJAX handlers. Specifically, the `mt_ajax_handler` function (and potentially others in `mt-aj…

Show full research plan

Research Plan: CVE-2026-32492 Missing Authorization in My Tickets

1. Vulnerability Summary

The My Tickets plugin for WordPress (versions <= 2.1.1) is vulnerable to Missing Authorization in its AJAX handlers. Specifically, the mt_ajax_handler function (and potentially others in mt-ajax.php) is registered for both authenticated (wp_ajax_) and unauthenticated (wp_ajax_nopriv_) users without adequate capability checks for certain internal functions.

The most likely vector involves the save_address functionality or the mt_ajax_load_model function, which allows unauthenticated users to perform actions or access data models that should be restricted. In version 2.1.1, the save_address function updates user metadata based on the current user object, which for unauthenticated users defaults to ID 0, potentially leading to database pollution or unauthorized metadata manipulation.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: mt_ajax_handler (for save_address) or mt_ajax_load_model.
  • Authentication: Unauthenticated (via wp_ajax_nopriv_mt_ajax_handler).
  • Preconditions:
    • The plugin must be active.
    • A valid nonce for the specific AJAX action must be obtained from a front-end page (e.g., an event
Research Findings
Static analysis — not yet PoC-verified

Summary

The My Tickets plugin for WordPress is vulnerable to Missing Authorization because several AJAX handlers, such as mt_ajax_handler and mt_ajax_load_model, are registered for unauthenticated users without internal capability checks. This allows unauthenticated attackers to perform unauthorized actions like updating user metadata or accessing restricted data models, provided they can obtain a valid security nonce from the site's front-end.

Vulnerable Code

// mt-ajax.php lines 224-225 (v2.1.1)
add_action( 'wp_ajax_mt_ajax_handler', 'mt_ajax_handler' );
add_action( 'wp_ajax_nopriv_mt_ajax_handler', 'mt_ajax_handler' );

---

// mt-ajax.php lines 212-222 (v2.1.1)
if ( 'save_address' === $_REQUEST['function'] ) {
    $post         = array_map( 'sanitize_text_field', $_REQUEST['data'] );
    $current_user = wp_get_current_user();
    $saved        = update_user_meta( $current_user->ID, '_mt_shipping_address', $post );
    $response     = array();
    if ( $saved ) {
        $response['response'] = apply_filters( 'mt_save_address_success', __( 'Address updated.', 'my-tickets' ) );
    } else {
        $response['response'] = apply_filters( 'mt_save_address_failure', __( 'Address not updated.', 'my-tickets' ) );
    }
    wp_send_json( $response );
}

---

// mt-ajax.php lines 230-244 (v2.1.1)
function mt_ajax_load_model() {
	// verify nonce.
	if ( ! check_ajax_referer( 'mt-load-model', 'security', false ) ) {
		wp_send_json(
			array(
				'response' => __( 'Invalid security response.', 'my-tickets' ),
				'form'     => '',
			)
		);
	}
	$model    = ( in_array( $_REQUEST['model'], array( 'continuous', 'discrete', 'event' ), true ) ) ? sanitize_key( $_REQUEST['model'] ) : false;
    // ... logic continues ...
}
add_action( 'wp_ajax_mt_ajax_load_model', 'mt_ajax_load_model' );
add_action( 'wp_ajax_nopriv_mt_ajax_load_model', 'mt_ajax_load_model' );

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.1/css/mt-cart.css /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.2/css/mt-cart.css
--- /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.1/css/mt-cart.css	2025-11-30 19:38:36.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.2/css/mt-cart.css	2026-02-24 21:48:10.000000000 +0000
@@ -178,6 +178,10 @@
 	text-align: end;
 }
 
+.mt-order legend {
+	float: none;
+}
+
 .mt_cart th .mt-datetime {
     font-weight: 400;
 }
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.1/mt-ajax.php /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.2/mt-ajax.php
--- /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.1/mt-ajax.php	2025-11-30 19:38:36.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.2/mt-ajax.php	2026-02-24 21:48:10.000000000 +0000
@@ -81,6 +81,15 @@
 		$data = map_deep( $data, 'sanitize_text_field' );
 		// reformat request data to multidimensional array.
 		$cart = mt_get_cart();
+		$lock = 'mt_add_to_cart_lock_' . sanitize_text_field( $_REQUEST['mt-cart-nonce'] );
+		if ( get_transient( $lock ) ) {
+			$return = array(
+				'response' => esc_html__( 'Another transaction is currently processing. Please try again shortly.', 'my-tickets' ),
+				'success'  => 0,
+			);
+			wp_send_json( $return );
+		}
+		set_transient( $lock, 1, 5 );
 
 		foreach ( $data as $k => $d ) {
 			if ( 'mt_tickets' === $k ) {
@@ -163,6 +172,7 @@
 			'event_id' => $submit['mt_event_id'],
 			'data'     => $count,
 		);
+		delete_transient( $lock );
 		wp_send_json( $return );
 	}
 	if ( 'save_address' === $_REQUEST['function'] ) {
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.1/mt-notifications.php /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.2/mt-notifications.php
--- /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.1/mt-notifications.php	2025-11-30 19:38:36.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.2/mt-notifications.php	2026-02-24 21:48:10.000000000 +0000
@@ -769,7 +769,7 @@
 	if ( function_exists( 'mc_draw_template' ) ) {
 		return mc_draw_template( $data, $template );
 	} else {
-		$template = stripcslashes( $template );
+		$template = wp_unslash( $template );
 		// If there are no brace characters, there is nothing to replace.
 		if ( strpos( $template, '{' ) === false ) {
 			return trim( $template );
@@ -802,7 +802,7 @@
 							}
 						}
 					} else { // don't do preg match (never required for RSS).
-						$template = stripcslashes( str_replace( '{' . $key . '}', $value, $template ) );
+						$template = wp_unslash( str_replace( '{' . $key . '}', $value, $template ) );
 					}
 				} // end {$key check.
 			}
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.1/mt-receipt.php /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.2/mt-receipt.php
--- /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.1/mt-receipt.php	2025-11-30 19:38:36.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.2/mt-receipt.php	2026-02-24 21:48:10.000000000 +0000
@@ -27,7 +27,7 @@
 				$nonce       = isset( $_POST['_wpnonce'] ) ? $_POST['_wpnonce'] : false;
 				$verify      = wp_verify_nonce( $nonce, 'mt-verify-email' );
 				$email       = sanitize_text_field( $_POST['mt-verify-email'] );
-				$is_verified = ( $verify && $email === get_post_meta( $receipt->ID, '_email', true ) ) ? true : false;
+				$is_verified = ( $verify && get_post_meta( $receipt->ID, '_email', true ) === $email ) ? true : false;
 			}
 			$cookie_receipt = ( isset( $_COOKIE['mt_purchase_receipt'] ) ) ? $_COOKIE['mt_purchase_receipt'] : false;
 			// Allow conditions: within 10 minutes of purchase & browser has a matching cookie; current user can view reports; user has verified email.
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.1/my-tickets.php /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.2/my-tickets.php
--- /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.1/my-tickets.php	2025-11-30 19:38:36.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/my-tickets/2.1.2/my-tickets.php	2026-02-24 21:48:10.000000000 +0000
@@ -17,11 +17,11 @@
  * License:     GPL-2.0+
  * License URI: http://www.gnu.org/license/gpl-2.0.txt
  * Domain Path: lang
- * Version:     2.1.1
+ * Version:     2.1.2
  */
 
 /*
-	Copyright 2014-2025  Joe Dolson (email : joe@joedolson.com)
+	Copyright 2014-2026  Joe Dolson (email : joe@joedolson.com)
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@
  * @return string Current My Tickets version.
  */
 function mt_get_current_version() {
-	$mt_version = '2.1.1';
+	$mt_version = '2.1.2';
 
 	return $mt_version;
 }

Exploit Outline

The exploit methodology involves targeting the WordPress AJAX endpoint (/wp-admin/admin-ajax.php) using actions registered for unauthenticated users. An attacker first navigates to a front-end event page to extract a valid security nonce (e.g., mt-cart-nonce or mt-load-model). Once obtained, the attacker sends a POST request to the AJAX endpoint. For example, by specifying the action 'mt_ajax_handler' and function 'save_address', the attacker can attempt to manipulate user metadata despite being unauthenticated. Alternatively, using 'mt_ajax_load_model' allows the attacker to trigger data model loading logic that is intended to be protected by authorization checks.

Check if your site is affected.

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