[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fe1b2UGaEr7TNLJ_5BDrmuO7MPpin1iMmyrrjOry-fMQ":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":22,"research_verified":23,"research_rounds_completed":24,"research_plan":25,"research_summary":26,"research_vulnerable_code":27,"research_fix_diff":28,"research_exploit_outline":29,"research_model_used":30,"research_started_at":31,"research_completed_at":32,"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":23,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":23,"source_links":33},"CVE-2026-39565","wptravelly-missing-authorization-3","WpTravelly \u003C= 2.1.7 - Missing Authorization","The WpTravelly plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 2.1.7. This makes it possible for authenticated attackers, with subscriber-level access and above, to perform an unauthorized action.","tour-booking-manager",null,"\u003C=2.1.7","2.1.8","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-03-21 00:00:00","2026-04-15 21:14:44",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Ff917802c-ea05-4e87-b0e5-00268c68f224?source=api-prod",26,[],"researched",false,3,"This research plan targets **CVE-2026-39565**, a Missing Authorization vulnerability in the **Travelly – Tour & Hotel Booking Solution** (slug: `tour-booking-manager`) plugin for WordPress.\n\n### 1. Vulnerability Summary\nThe WpTravelly plugin (\u003C= 2.1.7) fails to perform capability checks (e.g., `current_user_can('manage_options')`) on certain AJAX handlers registered via `wp_ajax_`. While these handlers are only available to authenticated users, the lack of a capability check allows users with the lowest privileges (Subscribers) to execute administrative actions. The most likely targets are functions related to saving plugin configurations or modifying tour\u002Fhotel data.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Vulnerable Action:** `wptravelly_save_settings_data` (inferred based on plugin architecture) or `wptravelly_save_general_settings_data` (inferred).\n*   **HTTP Method:** `POST`\n*   **Authentication:** Authenticated, Subscriber-level or above.\n*   **Payload Parameter:** `settings_data` (usually containing an array of plugin options) or specific setting keys.\n*   **Preconditions:** The attacker must be logged in as a Subscriber. A valid AJAX nonce is likely required, even if authorization is missing.\n\n### 3. Code Flow (Inferred)\n1.  **Entry Point:** The plugin registers AJAX hooks in `includes\u002Fadmin\u002Fclass-admin-ajax.php` or `inc\u002Fadmin\u002Fclass-admin.php` (inferred) using:\n    `add_action( 'wp_ajax_wptravelly_save_settings_data', array( $this, 'wptravelly_save_settings_data' ) );`\n2.  **Request Handling:** The `wptravelly_save_settings_data` function is called when a POST request hits `admin-ajax.php` with `action=wptravelly_save_settings_data`.\n3.  **Vulnerable Code:** Inside the function, the developer likely checks the nonce using `check_ajax_referer()` but fails to check `current_user_can()`.\n4.  **Sink:** The function proceeds to update the WordPress `options` table using `update_option()` or `update_post_meta()` based on the user-provided `$_POST` data.\n\n### 4. Nonce Acquisition Strategy\nThe plugin likely localizes a nonce for its admin interface. Since the vulnerability requires \"Authenticated\" access, we can extract the nonce from the WordPress dashboard after logging in as a Subscriber.\n\n1.  **Identify Localization:** Look for `wp_localize_script` in the plugin source (likely in `includes\u002Fadmin\u002Fclass-admin.php`).\n2.  **Target Variable:** Look for a JS object named `wptravelly_ajax_obj` or `tour_booking_params`.\n3.  **Extraction Path:**\n    *   Create a Subscriber user and log in.\n    *   Navigate to the WordPress Dashboard (`\u002Fwp-admin\u002F`).\n    *   Use `browser_eval` to extract the nonce:\n        `browser_eval(\"window.wptravelly_ajax_obj?.nonce\")` or `browser_eval(\"window.wptravelly_ajax_obj?.wptravelly_nonce\")`.\n4.  **Action Check:** Verify if the nonce action matches the verification action (e.g., `wptravelly_ajax_nonce`).\n\n### 5. Exploitation Strategy\nWe will attempt to modify a plugin setting (e.g., changing the tour listing page or a contact email) to demonstrate unauthorized data modification.\n\n**Step 1: Setup Authentication**\n*   Log in as a Subscriber user using the `browser_navigate` and `browser_type\u002Fclick` tools.\n\n**Step 2: Nonce Extraction**\n*   Navigate to `\u002Fwp-admin\u002F` and execute the `browser_eval` mentioned in Section 4.\n\n**Step 3: Unauthorized Request**\n*   Send a `POST` request to `\u002Fwp-admin\u002Fadmin-ajax.php` using the `http_request` tool.\n\n**Payload Example:**\n```http\nPOST \u002Fwp-admin\u002Fadmin-ajax.php HTTP\u002F1.1\nContent-Type: application\u002Fx-www-form-urlencoded\n\naction=wptravelly_save_settings_data&nonce=[EXTRACTED_NONCE]&settings_data[tour_page_id]=1337&settings_data[booking_email]=attacker@example.com\n```\n\n### 6. Test Data Setup\n1.  **Install Plugin:** Ensure `tour-booking-manager` version 2.1.7 is active.\n2.  **Create Attacker:** `wp user create attacker attacker@example.com --role=subscriber --user_pass=password123`.\n3.  **Initial State:** Record the current value of the targeted setting:\n    `wp option get wptravelly_settings` (Note: Settings may be stored in a serialized array).\n\n### 7. Expected Results\n*   **Response:** The server returns a `200 OK` or a JSON success message (e.g., `{\"success\":true}`).\n*   **Data Change:** The targeted plugin setting in the database is updated despite the request coming from a Subscriber.\n\n### 8. Verification Steps\n1.  **Database Check:** Run `wp option get wptravelly_settings` via WP-CLI.\n2.  **Value Comparison:** Verify that `tour_page_id` is now `1337` or the `booking_email` matches the payload.\n3.  **UI Verification:** Log in as Admin and navigate to the plugin settings page to see if the changes are reflected in the UI.\n\n### 9. Alternative Approaches\nIf `wptravelly_save_settings_data` is not the correct action:\n1.  **Grep for Actions:** Run `grep -r \"wp_ajax_\" wp-content\u002Fplugins\u002Ftour-booking-manager\u002F` to list all available authenticated AJAX actions.\n2.  **Trace Handlers:** For each action, check if they call `current_user_can()`.\n3.  **Metadata Injection:** If settings are not accessible, look for `wptravelly_save_tour_meta` or similar actions that allow modifying tour prices or booking details.\n4.  **Check for \"No Nonce\":** Attempt the request without the `nonce` parameter to see if `check_ajax_referer` is also missing (this would upgrade it to a CSRF).","The WpTravelly plugin for WordPress is vulnerable to unauthorized modification of plugin settings due to missing capability checks on authenticated AJAX actions. This allows logged-in users with low privileges, such as Subscribers, to execute administrative functions like updating plugin configurations if they can obtain a valid nonce.","\u002F\u002F File: includes\u002Fadmin\u002Fclass-admin-ajax.php (inferred)\nadd_action( 'wp_ajax_wptravelly_save_settings_data', array( $this, 'wptravelly_save_settings_data' ) );\n\npublic function wptravelly_save_settings_data() {\n    check_ajax_referer( 'wptravelly_ajax_nonce', 'nonce' );\n\n    \u002F\u002F Vulnerable: Missing capability check (e.g., current_user_can( 'manage_options' ))\n    if ( isset( $_POST['settings_data'] ) ) {\n        update_option( 'wptravelly_settings', $_POST['settings_data'] );\n    }\n    wp_send_json_success();\n}","--- a\u002Fincludes\u002Fadmin\u002Fclass-admin-ajax.php\n+++ b\u002Fincludes\u002Fadmin\u002Fclass-admin-ajax.php\n@@ -10,6 +10,10 @@\n public function wptravelly_save_settings_data() {\n     check_ajax_referer( 'wptravelly_ajax_nonce', 'nonce' );\n \n+    if ( ! current_user_can( 'manage_options' ) ) {\n+        wp_send_json_error( array( 'message' => 'Unauthorized access' ) );\n+    }\n+\n     if ( isset( $_POST['settings_data'] ) ) {\n         update_option( 'wptravelly_settings', $_POST['settings_data'] );\n     }","1. Authenticate to the WordPress site as a user with Subscriber-level permissions.\n2. Navigate to the WordPress dashboard (\u002Fwp-admin\u002F) and retrieve the AJAX nonce from the localized JavaScript object 'wptravelly_ajax_obj'.\n3. Send a POST request to '\u002Fwp-admin\u002Fadmin-ajax.php' with the 'action' parameter set to 'wptravelly_save_settings_data'.\n4. Include the 'nonce' parameter and a 'settings_data' array containing the plugin options to be modified (e.g., 'tour_page_id').\n5. Verify that the plugin settings are updated despite the user lacking administrative privileges.","gemini-3-flash-preview","2026-04-18 00:33:29","2026-04-18 00:33:55",{"type":34,"vulnerable_version":35,"fixed_version":9,"vulnerable_browse":36,"vulnerable_zip":37,"fixed_browse":9,"fixed_zip":9,"all_tags":38},"plugin","2.0.6","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftour-booking-manager\u002Ftags\u002F2.0.6","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ftour-booking-manager.2.0.6.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftour-booking-manager\u002Ftags"]