[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f0Uz_a-Qq8EoS7g8TIznNxODJ1AzhdgcrTa7XTd3JtGo":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":26,"research_verified":27,"research_rounds_completed":28,"research_plan":29,"research_summary":30,"research_vulnerable_code":31,"research_fix_diff":32,"research_exploit_outline":33,"research_model_used":34,"research_started_at":35,"research_completed_at":36,"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":27,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":27,"source_links":37},"CVE-2026-40791","wp-time-slots-booking-form-unauthenticated-stored-cross-site-scripting-2","WP Time Slots Booking Form \u003C= 1.2.46 - Unauthenticated Stored Cross-Site Scripting","The WP Time Slots Booking Form plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.2.46 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.","wp-time-slots-booking-form",null,"\u003C=1.2.46","1.2.47","high",7.2,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-04-23 00:00:00","2026-04-30 14:51:49",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fa051d96a-fe82-4223-839b-24cbb5b300d1?source=api-prod",8,[22,23,24,25],"README.txt","cp-admin-int-message-list.inc.php","cp-main-class.inc.php","wp-time-slots-booking-plugin.php","researched",false,3,"This research plan targets **CVE-2026-40791**, an unauthenticated stored Cross-Site Scripting (XSS) vulnerability in the **WP Time Slots Booking Form** plugin.\n\n### 1. Vulnerability Summary\nThe plugin fails to sanitize user-supplied data during the booking submission process and fails to escape that data when displaying it in the administrative \"Booking Orders\" list. An unauthenticated attacker can submit a booking request containing a malicious script in any form field. When an administrator views the bookings for that calendar, the script executes in their session context.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Action:** `cp_tslotsbooking_submit` (Inferred from class prefix `cp_tslotsbooking` in `cp-main-class.inc.php`).\n*   **Vulnerable Parameter:** Any form field submitted via POST (e.g., `email`, or additional custom fields like `fieldname2`).\n*   **Authentication:** None required (unauthenticated).\n*   **Preconditions:** A booking form (calendar) must be published on a public page to obtain a valid submission nonce and the calendar ID (`cal`).\n\n### 3. Code Flow\n1.  **Submission (Source):** An unauthenticated user submits a booking via AJAX. The plugin handles this in `cp-main-class.inc.php` (inside a method typically named `submit` or `process_submission` hooked to `wp_ajax_nopriv_cp_tslotsbooking_submit`).\n2.  **Storage:** The plugin iterates through `$_POST` data, serializes it, and inserts it into the `$wpdb->prefix . \"cptslotsbk_messages\"` table in the `posted_data` column.\n3.  **Retrieval:** An admin navigates to the \"Booking Orders\" page. `cp-admin-int-message-list.inc.php` is loaded.\n4.  **Processing:**\n    *   Line 116-121: The code fetches records from `$this->table_messages` (which is `cptslotsbk_messages`).\n    *   Line 144: The query results are stored in `$events`.\n    *   Line 70-76 (Example of processing): The code calls `unserialize($myrows[0]->posted_data)`.\n5.  **Rendering (Sink):** Although truncated in the snippet, the plugin typically iterates through the deserialized `posted_data` and echoes the keys and values into a table for the administrator. Because no `esc_html()` or `wp_kses()` is applied during this output, the XSS triggers.\n\n### 4. Nonce Acquisition Strategy\nThe booking submission requires a nonce generated for the specific form. This nonce is tied to the `uid=0` (anonymous user) session.\n\n1.  **Identify Shortcode:** The default shortcode is `[CP_TIME_SLOTS_BOOKING]`.\n2.  **Create Test Page:**\n    ```bash\n    wp post create --post_type=page --post_status=publish --post_title=\"Booking Test\" --post_content='[CP_TIME_SLOTS_BOOKING id=\"1\"]'\n    ```\n3.  **Navigate and Extract:**\n    Use `browser_navigate` to visit the new page.\n    Use `browser_eval` to extract the nonce from the localized JavaScript configuration object.\n    *   **Variable Name:** `cp_tslotsbooking_fbuilder_config`\n    *   **Nonce Path:** `cp_tslotsbooking_fbuilder_config.obj.nonce`\n    *   **Item ID:** `cp_tslotsbooking_fbuilder_config.obj.item_id` (This confirms the `cal` ID).\n\n### 5. Exploitation Strategy\nThe exploit involves a single POST request to the AJAX endpoint using the extracted nonce.\n\n**HTTP Request:**\n*   **Method:** POST\n*   **URL:** `http:\u002F\u002F\u003Ctarget>\u002Fwp-admin\u002Fadmin-ajax.php?action=cp_tslotsbooking_submit`\n*   **Content-Type:** `application\u002Fx-www-form-urlencoded`\n*   **Parameters:**\n    *   `cp_tslotsbooking_nonce`: `[EXTRACTED_NONCE]`\n    *   `item`: `1` (The calendar ID)\n    *   `fieldname1_date`: `2025-12-25` (Required for valid booking)\n    *   `fieldname1_slot`: `08:00 - 09:00` (Required for valid booking)\n    *   `email`: `admin@victim.com\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>`\n    *   `fieldname2`: `\u003Cimg src=x onerror=alert(\"XSS\")>` (Additional field often stored)\n\n### 6. Test Data Setup\n1.  Ensure the plugin is activated.\n2.  The default \"Form 1\" (ID 1) is created upon installation (as seen in `_install` in `cp-main-class.inc.php`).\n3.  Create a public page with the shortcode `[CP_TIME_SLOTS_BOOKING id=\"1\"]`.\n4.  Ensure no Captcha is blocking the request (the default is `true`, so the PoC may need to disable it via WP-CLI: `wp option update cp_tslotsbooking_cv_enable_captcha 'false'`).\n\n### 7. Expected Results\n*   The `admin-ajax.php` response should indicate a successful submission (usually a redirect URL or a JSON success message).\n*   When an admin visits `\u002Fwp-admin\u002Fadmin.php?page=cp_timeslotsbooking&cal=1&acc=messages`, the JavaScript payload will execute.\n\n### 8. Verification Steps\nAfter sending the HTTP request, verify the storage via WP-CLI:\n```bash\n# Check the cptslotsbk_messages table for the payload\nwp db query \"SELECT posted_data FROM wp_cptslotsbk_messages ORDER BY id DESC LIMIT 1\"\n```\nThe output should contain the serialized XSS string.\n\n### 9. Alternative Approaches\nIf `fieldname1` submission is too complex due to date\u002Ftime logic:\n*   **Inject via Search:** `cp-admin-int-message-list.inc.php` line 116 uses `$_GET[\"search\"]` in a SQL query but then likely reflects it in the \"Results for: ...\" text. Test `admin.php?page=cp_timeslotsbooking&cal=1&acc=messages&search=\u003Cscript>alert(1)\u003C\u002Fscript>`.\n*   **Status Update:** If an unauthenticated user can trigger a status update (unlikely due to admin checks), the `status` parameter in `update_status` might be a sink.\n*   **Manual Update Sink:** Line 72 uses `$_GET[\"status\"]` to update `posted_data` via the `lu` (load update) parameter. If this can be reached, it's an alternative storage vector.","The WP Time Slots Booking Form plugin is vulnerable to unauthenticated stored Cross-Site Scripting (XSS) due to a failure to sanitize input and escape output during the booking submission and display process. Attackers can inject malicious scripts into booking fields, which are then executed in the context of an administrator's session when they view the booking orders list.","\u002F\u002F cp-main-class.inc.php around line 1481\n'date' => $item_split[0],\n'slot' => $item_split[1],\n\n---\n\n\u002F\u002F cp-admin-int-message-list.inc.php around line 415\n$appts .=   '\u003Cdiv class=\"ahb-appointment-badge\">' .\n               '\u003Cspan class=\"dashicons dashicons-clock\">\u003C\u002Fspan>' .\n               '\u003Cspan class=\"ahb-time\">'.$this->format_date($posted_data[\"apps\"][$k][\"date\"]).' '.$posted_data[\"apps\"][$k][\"slot\"].'\u003C\u002Fspan>' .","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-time-slots-booking-form\u002F1.2.46\u002Fcp-admin-int-message-list.inc.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-time-slots-booking-form\u002F1.2.47\u002Fcp-admin-int-message-list.inc.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-time-slots-booking-form\u002F1.2.46\u002Fcp-admin-int-message-list.inc.php\t2026-03-27 17:30:42.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-time-slots-booking-form\u002F1.2.47\u002Fcp-admin-int-message-list.inc.php\t2026-04-10 09:44:46.000000000 +0000\n@@ -412,7 +412,7 @@\n     $app = $posted_data[\"apps\"][$k];\n     $appts .=   '\u003Cdiv class=\"ahb-appointment-badge\">' .\n                    '\u003Cspan class=\"dashicons dashicons-clock\">\u003C\u002Fspan>' .\n-                   '\u003Cspan class=\"ahb-time\">'.$this->format_date($posted_data[\"apps\"][$k][\"date\"]).' '.$posted_data[\"apps\"][$k][\"slot\"].'\u003C\u002Fspan>' .\n+                   '\u003Cspan class=\"ahb-time\">'.$this->format_date($posted_data[\"apps\"][$k][\"date\"]).' '.esc_html($posted_data[\"apps\"][$k][\"slot\"]).'\u003C\u002Fspan>' .\n                    '\u003Cspan class=\"ahb-service\">'.($app[\"quantity1\"] + $app[\"quantity2\"] + $app[\"quantity3\"] + $app[\"quantity4\"] + $app[\"quantity5\"] > 1 || $app[\"quantity1\"] == 0 ? \n \t\t\t\t      \" (\".(\n                       $this->getQuantityLabel(\"quantity1\",$app[\"field\"],$formdata).$app[\"quantity1\"]\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-time-slots-booking-form\u002F1.2.46\u002Fcp-main-class.inc.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-time-slots-booking-form\u002F1.2.47\u002Fcp-main-class.inc.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-time-slots-booking-form\u002F1.2.46\u002Fcp-main-class.inc.php\t2026-03-27 17:30:42.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-time-slots-booking-form\u002F1.2.47\u002Fcp-main-class.inc.php\t2026-04-10 09:44:46.000000000 +0000\n@@ -1478,8 +1478,8 @@\n                                      'cancelled' => $this->get_option('defaultstatus', ''),\n                                      'baseprice' => floatval($server_side_price),\n                                      'price' => floatval($server_side_price),\n-                                     'date' => $item_split[0],\n-                                     'slot' => $item_split[1],\n+                                     'date' => sanitize_text_field($item_split[0]),\n+                                     'slot' => sanitize_text_field($item_split[1]),\n                                      'quantity1' => $quantity1,\n                                      'quantity2' => $quantity2,\n                                      'quantity3' => $quantity3,","1. Identify a public page on the target site containing a booking form (shortcode [CP_TIME_SLOTS_BOOKING]).\n2. Extract the required submission nonce and item (calendar) ID from the localized JavaScript object `cp_tslotsbooking_fbuilder_config` in the page source.\n3. Construct a POST request to the WordPress AJAX endpoint `\u002Fwp-admin\u002Fadmin-ajax.php?action=cp_tslotsbooking_submit`.\n4. In the request body, include the extracted nonce and a payload for a slot-related field (e.g., `fieldname1_slot`) containing a malicious script tag like `\u003Cscript>alert(document.domain)\u003C\u002Fscript>`.\n5. Wait for an administrator to log in and navigate to the 'Booking Orders' page (accessible via the plugin menu) for that specific calendar ID.\n6. The script will execute automatically when the admin dashboard renders the appointment list containing the malicious payload.","gemini-3-flash-preview","2026-05-04 18:33:28","2026-05-04 18:34:09",{"type":38,"vulnerable_version":39,"fixed_version":11,"vulnerable_browse":40,"vulnerable_zip":41,"fixed_browse":42,"fixed_zip":43,"all_tags":44},"plugin","1.2.46","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwp-time-slots-booking-form\u002Ftags\u002F1.2.46","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwp-time-slots-booking-form.1.2.46.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwp-time-slots-booking-form\u002Ftags\u002F1.2.47","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwp-time-slots-booking-form.1.2.47.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwp-time-slots-booking-form\u002Ftags"]