CVE-2026-8892

CM Business Directory <= 1.5.7 - Authenticated (Contributor+) Stored Cross-Site Scripting via Business Address Meta Fields

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

Description

The CM Business Directory – Optimise and showcase local business plugin for WordPress is vulnerable to Stored Cross-Site Scripting via Business Address Meta Fields in all versions up to, and including, 1.5.7 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with contributor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. Because the malicious payload is stored in post meta rather than post_content, WordPress's unfiltered_html capability restriction does not apply, meaning contributors who lack that capability can still inject executable HTML via the address meta fields such as cmbd_address, cmbd_cityTown, cmbd_stateCounty, cmbd_postalcode, cmbd_region, and cmbd_country.

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.7
PublishedJuly 2, 2026
Last updatedJuly 3, 2026
Affected plugincm-business-directory

What Changed in the Fix

Changes introduced in v1.5.8

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-8892 ## 1. Vulnerability Summary The **CM Business Directory** plugin (<= 1.5.7) is vulnerable to **Stored Cross-Site Scripting (XSS)** via several business address meta fields. While WordPress core filters `post_content` based on the `unfiltered_html` capabil…

Show full research plan

Exploitation Research Plan: CVE-2026-8892

1. Vulnerability Summary

The CM Business Directory plugin (<= 1.5.7) is vulnerable to Stored Cross-Site Scripting (XSS) via several business address meta fields. While WordPress core filters post_content based on the unfiltered_html capability, it does not automatically sanitize data saved via update_post_meta.

In this plugin, the CMBusinessDirectoryBackend::saveMetabox function (hooked to save_post) fails to sanitize input for fields such as cmbd_address, cmbd_cityTown, and cmbd_country. Subsequently, the frontend templates (e.g., business-page-view.php) output these values using get_post_meta without proper escaping (e.g., esc_html or esc_attr). This allows a Contributor-level user to inject malicious scripts that execute in the context of any user (including Administrators) viewing the business page.

2. Attack Vector Analysis

  • Vulnerable Endpoint: wp-admin/post.php (via save_post hook).
  • Vulnerable Parameters: cmbd_address, cmbd_cityTown, cmbd_stateCounty, cmbd_postalcode, cmbd_region, cmbd_country.
  • Authentication Level: Authenticated (Contributor or higher).
  • Preconditions: The "CM Business Directory" plugin must be active. A Contributor must have permission to create/edit a cm-business post type.

3. Code Flow

  1. Entry Point: An authenticated user submits a POST request to wp-admin/post.php to save a cm-business post.
  2. Hook Execution: WordPress triggers the save_post action.
  3. Vulnerable Method: CMBusinessDirectoryBackend::saveMetabox (in backend/cm-business-directory-backend.php) is called.
  4. Data Storage (Sink): Inside saveMetabox, the code retrieves raw input from $_POST and calls update_post_meta($post_id, 'cmbd_address', $_POST['cmbd_address']) (and similar for other fields). No sanitization functions like sanitize_text_field() are applied.
  5. Rendering: When a user views the single business page, CMBusinessDirectoryBusinessPageView::content() (in frontend/templates/cm_default/business-page-view.php) is executed.
  6. XSS Trigger: The template calls get_post_meta and echoes the value directly into the HTML without esc_html() or esc_attr().

4. Nonce Acquisition Strategy

Since this exploit requires a Contributor to save a post, we must obtain the standard WordPress post-editing nonces and any plugin-specific metabox nonces.

  1. Identify the Post Type: The post type is defined by CMBusinessDirectoryShared::POST_TYPE (verbatim from backend/cm-business-directory-backend.php). Based on common patterns in this plugin, this is likely cm-business.
  2. Navigate to Editor: Use browser_navigate to go to wp-admin/post-new.php?post_type=cm-business.
  3. Extract Nonces:
    • The primary WordPress nonce for saving posts is usually in an input named _wpnonce.
    • Check for a custom metabox nonce. In backend/cm-business-directory-backend.php, the method addMetaBox is used. We will search the DOM for any hidden input fields containing "nonce".
  4. JavaScript Extraction:
    // Run via browser_eval
    {
        post_id: document.getElementById('post_ID')?.value,
        wpnonce: document.getElementById('_wpnonce')?.value,
        metabox_nonce: document.querySelector('input[name*="cmbd_address_nonce"]')?.value // (inferred name)
    }
    

5. Exploitation Strategy

Step 1: Preparation

  1. Login as a Contributor.
  2. Create a new cm-business post to get a valid post_ID and _wpnonce.

Step 2: Injection (HTTP POST)

Submit the payload to the address fields. We will use cmbd_address as the primary vector.

  • Tool: http_request
  • URL: https://<target>/wp-admin/post.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body Parameters:
    • action: editpost
    • post_ID: <ID_FROM_PREP>
    • _wpnonce: <NONCE_FROM_PREP>
    • post_type: cm-business
    • post_title: XSS Business Test
    • cmbd_address: 123 Malware Lane <script>alert(document.domain)</script>
    • cmbd_cityTown: London
    • cmbd_country: UK

Step 3: Trigger

The Contributor (or an Admin) views the newly created post. If the post is in "draft" status, use the preview link: https://<target>/?post_type=cm-business&p=<ID>&preview=true.

6. Test Data Setup

  1. User: Create a user with the contributor role.
  2. Plugin Config: Ensure the "CM Business Directory" plugin is active.
  3. Shortcode: The plugin renders via a template, but ensure a page exists with [cmbd_business] if testing the directory index. For the single page, WordPress handles it via single-cm-business.php (or similar template logic in the plugin).

7. Expected Results

  • The cmbd_address value in the database will contain the raw <script> tag.
  • Upon viewing the business page, the browser will execute the script, showing an alert box with the domain name.
  • The HTML source will look like: <div class="cmbd-address">123 Malware Lane <script>alert(document.domain)</script></div>.

8. Verification Steps

After the HTTP request, verify the storage using WP-CLI:

# Check the meta value directly in the database
wp post meta get <POST_ID> cmbd_address

Confirm the output matches the payload exactly, proving no sanitization occurred during update_post_meta.

9. Alternative Approaches

If cmbd_address is sanitized, test the following fields which often share the same vulnerable code path:

  • cmbd_cityTown
  • cmbd_stateCounty
  • cmbd_postalcode
  • cmbd_region
  • cmbd_country

Alternative Payload (Attribute Injection):
If the data is placed inside an attribute instead of a tag body:
" onmouseover="alert(1)

Check if your site is affected.

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