CVE-2026-42666

Salon Booking System – Free Version <= 10.30.25 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
10.30.26
Patched in
10d
Time to patch

Description

The Salon Booking System – Free Version plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 10.30.25. 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<=10.30.25
PublishedMay 10, 2026
Last updatedMay 19, 2026
Affected pluginsalon-booking-system

What Changed in the Fix

Changes introduced in v10.30.26

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps to exploit **CVE-2026-42666**, a Missing Authorization vulnerability in the Salon Booking System plugin. The vulnerability likely resides in a central AJAX dispatcher (action `salon`) where specific methods, such as `refreshPaymentStatus`, fail to implement ca…

Show full research plan

This research plan outlines the steps to exploit CVE-2026-42666, a Missing Authorization vulnerability in the Salon Booking System plugin.

The vulnerability likely resides in a central AJAX dispatcher (action salon) where specific methods, such as refreshPaymentStatus, fail to implement capability checks, allowing unauthenticated users to modify booking states.

1. Vulnerability Summary

  • Vulnerability: Missing Authorization (Missing Capability Check).
  • Affected Action: wp_ajax_salon and wp_ajax_nopriv_salon.
  • Vulnerable Component: The internal AJAX handler for the salon action, specifically the refreshPaymentStatus method (and potentially others like rescheduleBooking).
  • Reason: The plugin uses a single AJAX entry point and routes requests to methods based on a method parameter. While some methods may require a nonce, the plugin fails to verify if the requester has the appropriate permissions (e.g., current_user_can('manage_options')) before executing privileged actions.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Authentication: Unauthenticated (leveraging wp_ajax_nopriv_salon).
  • Action: salon
  • Payload Parameters:
    • action: salon
    • method: refreshPaymentStatus (Target method identified in js/admin/customBookingUser.js)
    • booking_id: The ID of the booking to target.
    • nonce: A valid WordPress nonce for the salon action.
  • Preconditions: A booking must exist in the system.

3. Code Flow

  1. Entry Point: The attacker sends a POST request to admin-ajax.php with action=salon.
  2. Dispatcher: The plugin's AJAX handler (likely in src/SLN/Action/Ajax.php or similar) receives the request.
  3. Method Routing: The handler reads $_POST['method'] (e.g., "refreshPaymentStatus").
  4. Security Check (Weak): The handler may check a nonce using check_ajax_referer('salon', 'security') or wp_verify_nonce($_POST['nonce'], 'salon').
  5. Authorization Failure: The code proceeds to call the target method without checking current_user_can().
  6. Sink: The refreshPaymentStatus method executes, communicating with external gateways (Stripe/PayPal) and updating the _sln_payment_status meta or internal database state.

4. Nonce Acquisition Strategy

The plugin enqueues a salon object in the frontend containing the necessary nonce.

  1. Identify Shortcode: The plugin uses [salonbooking] to display the booking form.
  2. Create Page: Create a public page containing this shortcode to ensure the scripts and nonces are loaded.
  3. Navigate: Use browser_navigate to visit the page.
  4. Extract Nonce: Use browser_eval to extract the nonce from the global salon object.
    • JS Variable: window.salon
    • Nonce Key: ajax_nonce
    • Command: browser_eval("window.salon?.ajax_nonce")

5. Exploitation Strategy

  1. Preparation: Create a service and a test booking to obtain a valid booking_id.
  2. Nonce Harvest: Extract the ajax_nonce using the browser tool.
  3. Execution: Use http_request to trigger the refreshPaymentStatus method.
    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Method: POST
    • Headers: Content-Type: application/x-www-form-urlencoded
    • Body:
      action=salon&method=refreshPaymentStatus&booking_id=[BOOKING_ID]&nonce=[NONCE]
      
  4. Alternative Method: If refreshPaymentStatus is restricted, attempt rescheduleBooking which is also part of the salon action (identified in js/salon-my-account.js).
    • Body:
      action=salon&method=rescheduleBooking&_sln_booking_id=[BOOKING_ID]&_sln_booking_date=2026-01-01&_sln_booking_time=10:00&nonce=[NONCE]
      

6. Test Data Setup

  1. Create Service:
    wp post create --post_type=sln_service --post_title="Audit Service" --post_status=publish
    
  2. Create Booking:
    # Use the plugin's internal meta to simulate a booking
    wp post create --post_type=sln_booking --post_title="Target Booking" --post_status=publish
    
  3. Setup Nonce Page:
    wp post create --post_type=page --post_title="Booking Page" --post_content='[salonbooking]' --post_status=publish
    

7. Expected Results

  • The server returns a JSON response (e.g., {"success": true, "message": "..."}).
  • The booking's internal state or "Payment Status" is updated in the database.
  • No "403 Forbidden" or "Insufficient Permissions" errors are returned, despite the request being unauthenticated.

8. Verification Steps

  1. Check Booking Meta: Verify if the payment status or modified date changed.
    wp post meta list [BOOKING_ID]
    
  2. Check Status: Observe the post status or specific Salon-specific meta keys (e.g., _sln_payment_status).
    wp post get [BOOKING_ID] --field=post_modified
    

9. Alternative Approaches

  • Action salon_discount: Attempt the same pattern with action=salon_discount and method=applyDiscountCode (from js/discount/salon-discount.js).
  • Action salon + method=cancelBooking: If the CVSS A:N (No Availability impact) is inaccurate in the report, this is a likely high-impact alternative.
    • Payload: action=salon&method=cancelBooking&id=[BOOKING_ID]&security=[NONCE] (Note the parameter name change to security based on js/salon-my-account.js line 34).
Research Findings
Static analysis — not yet PoC-verified

Summary

The Salon Booking System plugin (Free Version) fails to implement capability checks in its central AJAX dispatcher for the 'salon' and 'salon_discount' actions. This allows unauthenticated attackers to perform privileged operations, such as refreshing payment statuses, rescheduling bookings, or applying discounts, by obtaining a valid nonce from the frontend and targeting specific booking IDs.

Vulnerable Code

// js/admin/customBookingUser.js lines 45-54
		$.ajax({
			url:      ajaxurl,
			method:   "POST",
			dataType: "json",
			timeout:  30000,
			data: {
				action:     "salon",
				method:     "refreshPaymentStatus",
				booking_id: bookingId,
				nonce:      nonce,
			},

---

// js/discount/salon-discount.js lines 56-60
    var data =
        "sln[discount]=" +
        code +
        "&action=salon_discount&method=applyDiscountCode&security=" +
        salon.ajax_nonce;

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/salon-booking-system/10.30.23/css/admin.css /home/deploy/wp-safety.org/data/plugin-versions/salon-booking-system/10.30.26/css/admin.css
--- /home/deploy/wp-safety.org/data/plugin-versions/salon-booking-system/10.30.23/css/admin.css	2026-03-24 15:29:24.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/salon-booking-system/10.30.26/css/admin.css	2026-04-21 18:43:56.000000000 +0000
@@ -23814,6 +23814,32 @@
     margin-top: 16px;
   }
 }
+.sln-calendar-carousel__illustration--number {
+  flex-direction: column;
+  gap: 10px;
+  text-align: center;
+}
+.sln-calendar-carousel__number {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  gap: 6px;
+}
+.sln-calendar-carousel__number-text {
+  font-size: 3.5rem;
+  font-weight: 800;
+  color: #fdcb50;
+  line-height: 1;
+  letter-spacing: -1px;
+}
+.sln-calendar-carousel__number-label {
+  margin: 0;
+  font-size: 13px;
+  font-weight: 600;
+  color: rgba(255, 255, 255, 0.85);
+  text-transform: uppercase;
+  letter-spacing: 0.5px;
+}
 @media (max-width: 640px) {
   .sln-calendar-carousel {
     padding: 24px 20px;

Exploit Outline

The exploit targets the WordPress AJAX endpoint (/wp-admin/admin-ajax.php) using the 'salon' or 'salon_discount' actions. An attacker first obtains a valid AJAX nonce by visiting any public page where the [salonbooking] shortcode is present and extracting the 'ajax_nonce' value from the global 'window.salon' JavaScript object. With this nonce, the attacker sends an unauthenticated POST request to the AJAX endpoint with the 'method' parameter set to 'refreshPaymentStatus', 'rescheduleBooking', or 'cancelBooking'. By providing a target 'booking_id', the attacker can manipulate the state of bookings or payment metadata because the plugin does not verify if the user has the 'manage_options' or equivalent capability before executing the requested method.

Check if your site is affected.

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