EventPrime – Events Calendar, Bookings and Tickets <= 4.3.2.1 - Authenticated (Subscriber+) Stored Cross-Site Scripting
Description
The EventPrime – Events Calendar, Bookings and Tickets plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 4.3.2.1 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with subscriber-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=4.3.2.1What Changed in the Fix
Changes introduced in v4.3.2.2
Source Code
WordPress.org SVNI cannot fulfill this request. I am prohibited from generating actionable plans, payloads, or instructions for the exploitation of security vulnerabilities. If you are interested in web security from a defensive or research perspective, I can recommend the following resources for learning about Cro…
Show full research plan
I cannot fulfill this request. I am prohibited from generating actionable plans, payloads, or instructions for the exploitation of security vulnerabilities.
If you are interested in web security from a defensive or research perspective, I can recommend the following resources for learning about Cross-Site Scripting (XSS) prevention and secure WordPress development:
- WordPress Developer Documentation: Review the articles on Data Sanitization and Escaping to understand the correct use of functions like
esc_html(),esc_attr(), andwp_kses()to prevent XSS. - OWASP Top Ten: Explore the OWASP guidance on Injection and XSS to learn about common attack vectors and industry-standard mitigation strategies.
- WordPress Security Best Practices: Consult the official WordPress security guide for information on securing installations and managing user permissions effectively.
Summary
The EventPrime plugin for WordPress is vulnerable to Stored Cross-Site Scripting due to missing capability checks and insufficient sanitization in several AJAX handlers, combined with unsafe output rendering in administrative JavaScript files. This allows authenticated attackers with subscriber-level permissions to inject malicious scripts into plugin settings or metadata that execute when an administrator views the affected dashboard pages.
Vulnerable Code
// admin/js/ep-admin-license.js line 4 function showResult(btn, message, success = true) { const resultSpan = $(btn).closest('.ep-license-card-box').find('.ep-extension-action-result'); resultSpan.html(message).css('color', success ? 'green' : 'red'); } function showLicenseStatus(btn, message, success = true) { const resultSpan = $(btn).closest('.ep-license-status').find('.ep-extension-action-result'); resultSpan.html(message).css('color', success ? 'green' : 'red'); } --- // includes/class-ep-ajax.php line 3793 public function upload_license_file() { $license_json = $_POST['license_data'] ?? ''; if (empty($license_json)) { wp_send_json_error(['message' => 'No license data provided.']); } $license_data = json_decode(stripslashes($license_json), true); if (json_last_error() !== JSON_ERROR_NONE || empty($license_data) || !is_array($license_data)) { wp_send_json_error(['message' => 'Invalid license data format.']); } $all_license_data = get_option('metagauss_license_data', []); $i=0; foreach ($license_data as $license_key => $data) { if (empty($license_key)) { wp_send_json_error([ 'message' => esc_html__('License key not found.', 'eventprime-event-calendar-management'), ]); } if (!isset($data['plugins']) || !is_array($data['plugins'])) { wp_send_json_error([ 'message' => esc_html__('Invalid license data received.', 'eventprime-event-calendar-management'), ]); } if($i==0) { $license_primary_key = $license_key; } $i++; // Save to DB $all_license_data[$license_key] = [ 'plugins' => $data['plugins'] ]; } update_option('metagauss_license_data', $all_license_data); }
Security Fix
@@ -3,17 +3,33 @@ - function showResult(btn, message, success = true) { - const resultSpan = $(btn).closest('.ep-license-card-box').find('.ep-extension-action-result'); - resultSpan.html(message).css('color', success ? 'green' : 'red'); - } - - function showLicenseStatus(btn, message, success = true) { - const resultSpan = $(btn).closest('.ep-license-status').find('.ep-extension-action-result'); - resultSpan.html(message).css('color', success ? 'green' : 'red'); - } + function renderPlainMessage($container, message, success = true) { + $container.empty().css('color', success ? 'green' : 'red'); + + if (message && message.jquery) { + $container.append(message); + return; + } + + $container.text(message || ''); + } + + function showResult(btn, message, success = true) { + const resultSpan = $(btn).closest('.ep-license-card-box').find('.ep-extension-action-result'); + renderPlainMessage(resultSpan, message, success); + } + @@ -3793,6 +3808,18 @@ - public function upload_license_file() - { - - $license_json = $_POST['license_data'] ?? ''; + public function upload_license_file() + { + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error([ + 'message' => esc_html__( 'You are not allowed to manage licenses.', 'eventprime-event-calendar-management' ), + ]); + } + + if ( ! check_ajax_referer( 'ep-license-nonce', 'nonce', false ) ) { + wp_send_json_error([ + 'message' => esc_html__( 'Failed security checks.', 'eventprime-event-calendar-management' ), + ]); + }
Exploit Outline
1. Authenticate as a user with at least Subscriber-level privileges. 2. Locate the AJAX endpoint for `ep_upload_license_file` (or other unprotected handlers like `ep_save_license_settings`). 3. Craft a malicious JSON payload for the `license_data` parameter. Within the JSON structure, embed a script tag (e.g., `<script>alert(document.domain)</script>`) in values such as the plugin's name, version, or license keys. 4. Send a POST request to `wp-admin/admin-ajax.php` with the action set to `ep_upload_license_file` and the malicious `license_data`. Because the handler lacks capability checks in affected versions, the data is saved into the database (the `metagauss_license_data` option). 5. The payload is triggered when an administrator navigates to the license management page in the EventPrime dashboard. The plugin's JavaScript (ep-admin-license.js) retrieves the saved data and injects it into the DOM using the vulnerable `.html()` method, leading to script execution.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.