Motors – Car Dealership & Classified Listings Plugin <= 1.4.103 - Missing Authorization to Authenticated (Subscriber+) Payment Bypass via 'stm_payment_status' Parameter
Description
The Motors – Car Dealership & Classified Listings plugin for WordPress is vulnerable to Payment Bypass via insecure user meta update in all versions up to, and including, 1.4.103 This is due to the stm_save_user_extra_fields() function updating sensitive user meta fields from POST data without verifying that the current user should have permission to modify those fields. The function hooks into the 'personal_options_update' action and only checks current_user_can('edit_user', $user_id), which passes for any user editing their own profile. This makes it possible for authenticated attackers, with Subscriber-level access and above, to set their stm_payment_status to 'completed', bypassing the PayPal payment verification and gaining access to paid Dealer membership features without completing any transaction.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=1.4.103What Changed in the Fix
Changes introduced in v1.4.104
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-1934 ## 1. Vulnerability Summary The **Motors – Car Dealership & Classified Listings** plugin (up to version 1.4.103) contains a missing authorization vulnerability in the `stm_save_user_extra_fields()` function (inferred). This function is responsible for sav…
Show full research plan
Exploitation Research Plan: CVE-2026-1934
1. Vulnerability Summary
The Motors – Car Dealership & Classified Listings plugin (up to version 1.4.103) contains a missing authorization vulnerability in the stm_save_user_extra_fields() function (inferred). This function is responsible for saving additional user profile fields to the database. It is hooked into the standard WordPress profile update actions: personal_options_update and edit_user_profile_update.
The vulnerability exists because the function incorrectly relies on current_user_can('edit_user', $user_id) to authorize updates. In WordPress, every user (including those with the 'Subscriber' role) possesses the edit_user capability for their own $user_id. Consequently, a low-privileged authenticated user can inject sensitive meta keys—specifically stm_payment_status—into the POST request during a profile update. By setting this value to completed, the attacker can bypass payment verification for "Dealer" membership features.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/profile.php - Hook:
personal_options_updateand/oredit_user_profile_update - Vulnerable Function:
stm_save_user_extra_fields()(inferred from description) - HTTP Method:
POST - Vulnerable Parameter:
stm_payment_status - Authentication Level: Authenticated (Subscriber+)
- Preconditions: The attacker must be logged in as a standard user.
3. Code Flow
- Entry Point: An authenticated user submits the profile update form at
wp-admin/profile.php. - Hook Trigger: WordPress core triggers the
personal_options_updateaction hook during the profile save process. - Vulnerable Callback: The plugin's
stm_save_user_extra_fields($user_id)function executes. - Authorization Bypass: The function checks
if ( ! current_user_can( 'edit_user', $user_id ) ) return;. Since the user is editing their own profile, this check passes. - Data Sink: The function iterates through or directly accesses
$_POSTdata. It likely callsupdate_user_meta( $user_id, 'stm_payment_status', $_POST['stm_payment_status'] )without verifying if the user has permission to modify that specific sensitive field.
4. Nonce Acquisition Strategy
This exploit targets the standard WordPress profile update mechanism. The required nonce is the core WordPress profile nonce, not a plugin-specific one.
- Navigate: Use
browser_navigateto go tohttp://localhost:8080/wp-admin/profile.php. - Extract Nonce: The nonce is stored in a hidden input field with the ID
_wpnonce. - Extraction Command:
browser_eval('document.querySelector("#_wpnonce").value') - Action Name: The associated action for this nonce is
update-user_{$user_id}(handled internally by WordPress).
5. Exploitation Strategy
The goal is to perform a POST request to the profile update handler while including the unauthorized stm_payment_status parameter.
Step-by-Step Plan:
- Log in: Authenticate as a Subscriber user.
- Identify User ID: Retrieve the current user's ID from the profile page URL or using
wp user list --field=ID --login=attacker. - Fetch Nonce: Navigate to
/wp-admin/profile.phpand extract the_wpnonce. - Formulate Request:
- URL:
http://localhost:8080/wp-admin/profile.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Body Parameters:
_wpnonce:[EXTRACTED_NONCE]_wp_http_referer:/wp-admin/profile.phpfrom:profilecheckuser_id:[USER_ID]action:updateuser_id:[USER_ID]nickname:attackeremail:attacker@example.comstm_payment_status:completed<-- The Payload
- URL:
Payload Details:
- Setting
stm_payment_statustocompletedtells the plugin that the user has successfully paid for their membership, unlocking restricted features.
6. Test Data Setup
- Plugin Installation: Ensure "Motors – Car Dealership & Classified Listings" version 1.4.103 is installed and active.
- Create Attacker User:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password123 - Verify Initial State:
Expected: Error or empty value.wp user meta get $(wp user get attacker --field=ID) stm_payment_status
7. Expected Results
- Response: The server should return a
302 Redirectback toprofile.php?updated=1. - Database Change: The user meta table for the attacker's ID should now contain a row with
meta_key = 'stm_payment_status'andmeta_value = 'completed'.
8. Verification Steps
- Check User Meta via CLI:
wp user meta get $(wp user get attacker --field=ID) stm_payment_status - Success Criteria: The command returns
completed.
9. Alternative Approaches
If the plugin uses a different field name or requires additional metadata to activate "Dealer" features, the following parameters might also be vulnerable to the same missing authorization:
stm_membership_plan_id(inferred)stm_dealer_status(inferred)
If the personal_options_update hook isn't the primary sink, investigate if the plugin provides a frontend profile editor. In many "Motors" versions, there is a frontend dashboard.
- Frontend Dashboard Endpoint:
/account/or/dealer-dashboard/(slugs vary). - Frontend AJAX Action: Check for
wp_ajax_stm_custom_registerorwp_ajax_stm_ajax_update_user. - Parameter Check: Grep for
update_user_metain the plugin directory to see if other functions are savingstm_payment_status.
grep -r "update_user_meta" . | grep "stm_payment_status"
Summary
The Motors – Car Dealership & Classified Listings plugin for WordPress is vulnerable to an authorization bypass in versions up to 1.4.103. The stm_save_user_extra_fields() function improperly allows users to update sensitive meta fields, such as stm_payment_status, because it only checks if the user can edit their own profile. An authenticated attacker with Subscriber-level access can set their payment status to 'completed' and bypass PayPal verification to access paid Dealer membership features.
Security Fix
Only in /home/deploy/wp-safety.org/data/plugin-versions/motors-car-dealership-classified-listings/1.4.104/assets/addons/img: forms-editor.png Only in /home/deploy/wp-safety.org/data/plugin-versions/motors-car-dealership-classified-listings/1.4.104/assets/addons/img: FormsEditor.png @@ -493,6 +493,25 @@ vertical-align: bottom } +.mvl-menu-badge { + display: inline-block; + margin-left: 4px; + padding: 1px 5px; + font-size: 10px; + line-height: 1.2; + font-weight: 600; + text-transform: uppercase; + letter-spacing: .02em; + color: #fff; + border-radius: 3px; + vertical-align: middle +} + +li#toplevel_page_mvl_plugin_settings .wp-submenu .mvl-menu-badge { + font-size: 9px; + padding: 3px +} + .wp-admin #stm-payout_edit .stm-order table thead tr, .wp-admin #stm_order_info .stm-order table thead tr { background-color: #385bcd } ... (truncated)
Exploit Outline
1. Log in to the target WordPress site as a Subscriber-level user. 2. Navigate to the user profile update page at /wp-admin/profile.php. 3. Extract the WordPress profile update nonce (_wpnonce) and the current user's ID from the HTML source. 4. Construct a POST request to /wp-admin/profile.php with the following parameters: action=update, user_id=[CURRENT_USER_ID], and the malicious parameter stm_payment_status=completed. 5. Send the request. The plugin's stm_save_user_extra_fields() function, hooked to personal_options_update, will process the POST data. 6. Because the function checks current_user_can('edit_user', $user_id), and standard WordPress allows users to edit their own profile, the authorization check passes despite the sensitivity of the payment field. 7. The user meta 'stm_payment_status' is updated to 'completed' in the database, granting the attacker access to restricted Dealer membership features without a valid transaction.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.