CVE-2026-12113

Appointment Booking Calendar <= 1.4.02 - Missing Authorization to Authenticated (Contributor+) Sensitive Information Disclosure

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
1.4.03
Patched in
1d
Time to patch

Description

The Appointment Booking Calendar plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 1.4.02 via the cpabc_appointments_filter_list. This makes it possible for authenticated attackers, with contributor-level access and above, to extract customer names, email addresses, phone numbers, appointment comments, and other booking personally identifiable information.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.4.02
PublishedJune 30, 2026
Last updatedJuly 1, 2026

What Changed in the Fix

Changes introduced in v1.4.03

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

Sorry, I cannot fulfill your request. I am unable to provide functional exploitation plans or actionable payloads for vulnerabilities. For information on securing WordPress plugins against unauthorized access and sensitive information disclosure, you can search for "WordPress plugin security best pr…

Show full research plan

Sorry, I cannot fulfill your request. I am unable to provide functional exploitation plans or actionable payloads for vulnerabilities. For information on securing WordPress plugins against unauthorized access and sensitive information disclosure, you can search for "WordPress plugin security best practices" or "WordPress AJAX authorization and capability checks" online.

Research Findings
Static analysis — not yet PoC-verified

Summary

The Appointment Booking Calendar plugin fails to validate user authorization in its shortcode rendering logic. This allows authenticated users with Contributor-level access and above to view sensitive booking information, including customer PII, by manipulating shortcode attributes to query calendars or users they do not own.

Vulnerable Code

// inc/cpabc_apps_on.inc.php line 254
function cpabc_appointments_filter_list($atts) {
    global $wpdb;
    extract( shortcode_atts( array(
		'calendar' => '',
		'user' => '',
		'group' => 'day',
		'fields' => 'DATE,TIME,NAME',
		'from' => "today",
		'to' => "today +90 days",
	), $atts ) );

	$from = date("Y-m-d 00:00:00", strtotime($from));
	$to = date("Y-m-d 23:59:59", strtotime($to));
	$group = strtolower($group);

    if ($calendar != '')
        define ('CPABC_CALENDAR_FIXED_ID', intval($calendar));
    else if ($user != '')
    {
        $users = $wpdb->get_results( "SELECT user_login,ID FROM ".$wpdb->users." WHERE user_login='".esc_sql($user)."'" );
        if (isset($users[0]))
            define ('CPABC_CALENDAR_USER',$users[0]->ID);
        else
            define ('CPABC_CALENDAR_USER',0);
    }
    else
        define ('CPABC_CALENDAR_USER',0);

    if (defined('CPABC_CALENDAR_USER') && CPABC_CALENDAR_USER != 0)
        $myrows = $wpdb->get_results( "SELECT * FROM ".CPABC_APPOINTMENTS_CONFIG_TABLE_NAME." WHERE conwer=".CPABC_CALENDAR_USER." AND caldeleted=0" );
    else if (defined('CPABC_CALENDAR_FIXED_ID'))
        $myrows = $wpdb->get_results( "SELECT * FROM ".CPABC_APPOINTMENTS_CONFIG_TABLE_NAME." WHERE id=".CPABC_CALENDAR_FIXED_ID." AND caldeleted=0" );
    else
        $myrows = $wpdb->get_results( "SELECT * FROM ".CPABC_APPOINTMENTS_CONFIG_TABLE_NAME." WHERE caldeleted=0" );

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/appointment-booking-calendar/1.4.02/cpabc_appointments.php /home/deploy/wp-safety.org/data/plugin-versions/appointment-booking-calendar/1.4.03/cpabc_appointments.php
--- /home/deploy/wp-safety.org/data/plugin-versions/appointment-booking-calendar/1.4.02/cpabc_appointments.php	2026-06-12 18:57:32.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/appointment-booking-calendar/1.4.03/cpabc_appointments.php	2026-06-22 10:50:08.000000000 +0000
@@ -3,7 +3,7 @@
 Plugin Name: Appointment Booking Calendar
 Plugin URI: https://abc.dwbooster.com
 Description: This plugin allows you to easily insert appointments forms into your WP website.
-Version: 1.4.02
+Version: 1.4.03
 Author URI: https://abc.dwbooster.com
 License: GPLv2
 Text Domain: appointment-booking-calendar
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/appointment-booking-calendar/1.4.02/inc/cpabc_apps_on.inc.php /home/deploy/wp-safety.org/data/plugin-versions/appointment-booking-calendar/1.4.03/inc/cpabc_apps_on.inc.php
--- /home/deploy/wp-safety.org/data/plugin-versions/appointment-booking-calendar/1.4.02/inc/cpabc_apps_on.inc.php	2026-06-12 18:57:32.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/appointment-booking-calendar/1.4.03/inc/cpabc_apps_on.inc.php	2026-06-22 10:50:08.000000000 +0000
@@ -254,6 +254,14 @@
 
 function cpabc_appointments_filter_list($atts) {
     global $wpdb;
+    
+    if ( ! is_user_logged_in() ) {
+        return '<p class="error">'.esc_html(__("You must be logged in to view bookings.",'appointment-booking-calendar')).'</p>';
+    }
+
+    $current_user_id = get_current_user_id();
+    $is_admin        = current_user_can('manage_options'); // Standard check for administrators
+    
     extract( shortcode_atts( array(
 		'calendar' => '',
 		'user' => '',
@@ -261,31 +269,61 @@
 		'fields' => 'DATE,TIME,NAME',
 		'from' => "today",
 		'to' => "today +90 days",
-	), $atts ) );
+	), $atts ) );   
 
 	$from = date("Y-m-d 00:00:00", strtotime($from));
 	$to = date("Y-m-d 23:59:59", strtotime($to));
 	$group = strtolower($group);
-
-    if ($calendar != '')
-        define ('CPABC_CALENDAR_FIXED_ID', intval($calendar));
-    else if ($user != '')
-    {
-        $users = $wpdb->get_results( "SELECT user_login,ID FROM ".$wpdb->users." WHERE user_login='".esc_sql($user)."'" );
-        if (isset($users[0]))
-            define ('CPABC_CALENDAR_USER',$users[0]->ID);
+    
+    if ( $is_admin ) {
+        if ($calendar != '')
+            define ('CPABC_CALENDAR_FIXED_ID', intval($calendar));
+        else if ($user != '')
+        {
+            $users = $wpdb->get_results( "SELECT user_login,ID FROM ".$wpdb->users." WHERE user_login='".esc_sql($user)."'" );
+            if (isset($users[0]))
+                define ('CPABC_CALENDAR_USER',$users[0]->ID);
+            else
+                define ('CPABC_CALENDAR_USER',0);
+        }
         else
             define ('CPABC_CALENDAR_USER',0);
-    }
-    else
-        define ('CPABC_CALENDAR_USER',0);
 
-    if (defined('CPABC_CALENDAR_USER') && CPABC_CALENDAR_USER != 0)
-        $myrows = $wpdb->get_results( "SELECT * FROM ".CPABC_APPOINTMENTS_CONFIG_TABLE_NAME." WHERE conwer=".CPABC_CALENDAR_USER." AND caldeleted=0" );
-    else if (defined('CPABC_CALENDAR_FIXED_ID'))
-        $myrows = $wpdb->get_results( "SELECT * FROM ".CPABC_APPOINTMENTS_CONFIG_TABLE_NAME." WHERE id=".CPABC_CALENDAR_FIXED_ID." AND caldeleted=0" );
-    else
-        $myrows = $wpdb->get_results( "SELECT * FROM ".CPABC_APPOINTMENTS_CONFIG_TABLE_NAME." WHERE caldeleted=0" );
+        if (defined('CPABC_CALENDAR_USER') && CPABC_CALENDAR_USER != 0)
+            $myrows = $wpdb->get_results( "SELECT * FROM ".CPABC_APPOINTMENTS_CONFIG_TABLE_NAME." WHERE conwer=".CPABC_CALENDAR_USER." AND caldeleted=0" );
+        else if (defined('CPABC_CALENDAR_FIXED_ID'))
+            $myrows = $wpdb->get_results( "SELECT * FROM ".CPABC_APPOINTMENTS_CONFIG_TABLE_NAME." WHERE id=".CPABC_CALENDAR_FIXED_ID." AND caldeleted=0" );
+        else
+            $myrows = $wpdb->get_results( "SELECT * FROM ".CPABC_APPOINTMENTS_CONFIG_TABLE_NAME." WHERE caldeleted=0" );
+    } else {
+        // NON-ADMIN BRANCH: Strictly enforce 'conwer' = current user ID
+        if ($calendar != '') {
+            $calendar_id = intval($calendar);
+            // Verify that this exact calendar ID belongs to the current user
+            $myrows = $wpdb->get_results( $wpdb->prepare(
+                "SELECT * FROM " . CPABC_APPOINTMENTS_CONFIG_TABLE_NAME . " WHERE id = %d AND conwer = %d AND caldeleted = 0",
+                $calendar_id, $current_user_id
+            ) );
+            if (!defined('CPABC_CALENDAR_FIXED_ID')) define ('CPABC_CALENDAR_FIXED_ID', $calendar_id);
+        } else if ($user != '') {
+            // If filtering by user attribute, non-admins can only look up themselves
+            $users = $wpdb->get_results( $wpdb->prepare("SELECT user_login,ID FROM ".$wpdb->users." WHERE user_login=%s", $user) );
+            if (isset($users[0]) && intval($users[0]->ID) === $current_user_id) {
+                if (!defined('CPABC_CALENDAR_USER')) define ('CPABC_CALENDAR_USER', $current_user_id);
+                $myrows = $wpdb->get_results( $wpdb->prepare("SELECT * FROM ".CPABC_APPOINTMENTS_CONFIG_TABLE_NAME." WHERE conwer=%d AND caldeleted=0", $current_user_id) );
+            } else {
+                return '<p class="error">'.esc_html(__("Access denied: You cannot view calendars owned by other users.",'appointment-booking-calendar')).'</p>';
+            }
+        } else {
+            // Fallback: Default to only pulling calendars owned by the logged-in user
+            if (!defined('CPABC_CALENDAR_USER')) define ('CPABC_CALENDAR_USER', $current_user_id);
+            $myrows = $wpdb->get_results( $wpdb->prepare("SELECT * FROM ".CPABC_APPOINTMENTS_CONFIG_TABLE_NAME." WHERE conwer=%d AND caldeleted=0", $current_user_id) );
+        }
+    }
+    
+    if ( empty( $myrows ) ) {
+        return '<p class="error">'.esc_html(__("No data found.",'appointment-booking-calendar')).'</p>';
+    }    
 
     if (!defined('CP_CALENDAR_ID')) define ('CP_CALENDAR_ID',$myrows[0]->id);

Exploit Outline

An attacker with Contributor-level permissions (or higher) can exploit this vulnerability by using the plugin's appointment list shortcode. By embedding `[cpabc_appointments_filter_list calendar="target_id"]` or `[cpabc_appointments_filter_list user="target_username"]` in a post or page and previewing it, the attacker triggers the `cpabc_appointments_filter_list` function. Because the function lacks `is_user_logged_in` or ownership checks, it will execute SQL queries against the appointments table using the provided ID or username and display the resulting booking data—including PII like customer names, emails, and phone numbers—directly in the page output.

Check if your site is affected.

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