Motors – Car Dealership & Classified Listings Plugin <= 1.4.109 - Unauthenticated SQL Injection
Description
The Motors – Car Dealership & Classified Listings Plugin plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 1.4.109 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
<=1.4.109What Changed in the Fix
Changes introduced in v1.4.110
Source Code
WordPress.org SVN_filtered_users`: `$distance_order` is interpolated directly. Where does `$distance_order` come from? `UserController::get_dealers` calls: `$model->order_by_location( $lat )` If `order_by_location` returns a string containing `$lat` and `$lat` isn't escaped... But…
Show full research plan
_filtered_users: $distance_orderis interpolated directly. Where does$distance_ordercome from? UserController::get_dealerscalls: $model->order_by_location( $lat ) Iforder_by_locationreturns a string containing$latand$latisn't escaped... Butlatis checked withfloatval`.
- Let's look at the parameters in `stm_listings_template_actions` again.
Wait, look at this:
`$action = apply_filters( 'stm_listings_input', null, 'ajax_action' );`
The `stm_listings_input` filter is likely the source.
In many Stylemix plugins, `stm_listings_input` returns `$_GET[$key]` or `$_POST[$key]`.
If the code uses `stm_listings_input(null, 'some_param')` and injects it...
- Look at `includes/actions.php` -> `listings-result`:
```php
if ( stm_is_multilisting() && ! empty( $_GET['posttype'] ) && ... ) {
set_query_var( 'listings_type', $_GET['posttype'] );
HooksMultiListing::stm_listings_attributes_filter( array( 'slug' => $_GET['posttype'] ) );
}
```
Summary
The Motors – Car Dealership & Classified Listings Plugin is vulnerable to unauthenticated SQL Injection via the 'stm_lat' and 'stm_lng' parameters. These values are used to calculate distances in dealer searches and are concatenated directly into SQL queries without proper sanitization or parameter binding, allowing attackers to extract sensitive data from the database.
Vulnerable Code
// includes/class/User/UserController.php $lat = apply_filters( 'stm_listings_input', null, 'stm_lat' ); $lng = apply_filters( 'stm_listings_input', null, 'stm_lng' ); $radius = apply_filters( 'motors_vl_get_nuxy_mod', '', 'distance_search' ); $radius = ( ! empty( $radius ) ) ? $radius : 5000; if ( empty( $left_join ) && ! empty( floatval( $lat ) ) && ! empty( floatval( $lng ) ) ) { $include_users = $model->get_filtered_users_by_location( $model->fields_by_location( $lat, $lng ), $model->join_by_location( $lat ), $model->having_by_location( $lat, $radius ), $model->order_by_location( $lat ) ); } --- // includes/class/User/Model/UserModel.php public function fields_by_location( $lat, $lng ) { if ( empty( $lat ) ) { return ''; } $formula = "6378.137 * ACOS(COS(RADIANS(stm_lat_prefix.meta_value)) * COS(RADIANS($lat)) * COS(RADIANS(stm_lng_prefix.meta_value) - RADIANS($lng)) + SIN(RADIANS(stm_lat_prefix.meta_value)) * SIN(RADIANS($lat))) AS distance"; return ", $formula"; }
Security Fix
@@ -191,9 +191,13 @@ } public function fields_by_location( $lat, $lng ) { - if ( empty( $lat ) ) { + if ( false === filter_var( $lat, FILTER_VALIDATE_FLOAT ) || false === filter_var( $lng, FILTER_VALIDATE_FLOAT ) ) { return ''; } + + $lat = (float) $lat; + $lng = (float) $lng; + $formula = "6378.137 * ACOS(COS(RADIANS(stm_lat_prefix.meta_value)) * COS(RADIANS($lat)) * COS(RADIANS(stm_lng_prefix.meta_value) - RADIANS($lng)) + SIN(RADIANS(stm_lat_prefix.meta_value)) @@ -203,7 +207,7 @@ } public function join_by_location( $lat ) { - if ( empty( $lat ) ) { + if ( false === filter_var( $lat, FILTER_VALIDATE_FLOAT ) ) { return ''; } $join = " JOIN $this->user_meta_table AS stm_lat_prefix ON (u.ID = stm_lat_prefix.user_id AND stm_lat_prefix.meta_key = 'stm_dealer_location_lat')"; @@ -213,15 +217,17 @@ } public function having_by_location( $lat, $radius ) { - if ( empty( $lat ) ) { + if ( false === filter_var( $lat, FILTER_VALIDATE_FLOAT ) || false === filter_var( $radius, FILTER_VALIDATE_FLOAT ) ) { return ''; } + $radius = (float) $radius; + return "HAVING distance <= $radius"; } public function order_by_location( $lat ) { - if ( empty( $lat ) ) { + if ( false === filter_var( $lat, FILTER_VALIDATE_FLOAT ) ) { return ''; } @@ -64,12 +64,12 @@ } } - $lat = apply_filters( 'stm_listings_input', null, 'stm_lat' ); - $lng = apply_filters( 'stm_listings_input', null, 'stm_lng' ); - $radius = apply_filters( 'motors_vl_get_nuxy_mod', '', 'distance_search' ); - $radius = ( ! empty( $radius ) ) ? $radius : 5000; + $lat = filter_var( apply_filters( 'stm_listings_input', null, 'stm_lat' ), FILTER_VALIDATE_FLOAT ); + $lng = filter_var( apply_filters( 'stm_listings_input', null, 'stm_lng' ), FILTER_VALIDATE_FLOAT ); + $radius = filter_var( apply_filters( 'motors_vl_get_nuxy_mod', '', 'distance_search' ), FILTER_VALIDATE_FLOAT ); + $radius = ( false !== $radius && $radius > 0 ) ? $radius : 5000; - if ( empty( $left_join ) && ! empty( floatval( $lat ) ) && ! empty( floatval( $lng ) ) ) { + if ( empty( $left_join ) && false !== $lat && false !== $lng ) {
Exploit Outline
The exploit targets the dealer listing functionality. An unauthenticated attacker can provide malicious SQL within the 'stm_lat' or 'stm_lng' query parameters. Although the plugin performs a loose check using `floatval()`, it passes the original string values to `UserModel` methods. These methods interpolate the strings directly into a complex SQL formula involving geographic coordinates. By crafting a payload like '1) [INJECTED SQL]', an attacker can break out of the `RADIANS()` function call and execute arbitrary SQL commands to exfiltrate data via error-based or time-based injection techniques.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.