Simply Schedule Appointments <= 1.6.11.0 - Missing Authorization
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:NTechnical Details
<=1.6.11.0Source Code
WordPress.org SVNPatched version not available.
# 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_appointmentorssa_update_appointment
- REST Route (Inferred):
- HTTP Method:
POSTorDELETE - 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)
- The plugin registers REST routes or AJAX handlers during
initorrest_api_init. - A handler (e.g.,
cancel_appointmentin a REST controller or AJAX class) is defined. - The handler is registered with
permission_callback => '__return_true'or lacks acurrent_user_can()check entirely. - The function takes an
appointment_idfrom the request. - It calls a business logic function (e.g.,
SSA_Appointments::cancel()) to update the database. - 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.
- Identify Shortcode: The plugin's primary shortcode is
[ssa_booking]. - Create Test Page:
wp post create --post_type=page --post_title="Booking Test" --post_status=publish --post_content='[ssa_booking]' - Navigate and Extract: Use
browser_navigateto the new page. - JavaScript Extraction: The plugin localizes data into a JavaScript object. Based on common SSA versions, we will look for
ssa_booking_settingsorssa_booking_data.- Variable Name:
window.ssa_booking_settings(inferred) - Nonce Key:
nonceorrest_nonce - Command:
browser_eval("window.ssa_booking_settings?.rest_nonce || window.ssa_booking_data?.nonce")
- Variable Name:
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/jsonX-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
- Install Plugin: Ensure
simply-schedule-appointmentsis installed and active. - 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.
- 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 OKor204 No Contentresponse, often returning a JSON object indicating the status is now "cancelled". - Impact: The appointment status in the database changes from
scheduledorpendingtocancelledwithout the attacker ever logging in or providing a private "cancellation hash".
8. Verification Steps
- Check the database state using WP-CLI:
wp db query "SELECT status FROM wp_ssa_appointments WHERE id = <TARGET_ID>;" - Confirm the status is
cancelled. - 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).
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.