Broadstreet <= 1.53.1 - Authenticated (Subscriber+) Information Disclosure
Description
The Broadstreet plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 1.53.1 via the get_sponsored_meta() AJAX action. This makes it possible for authenticated attackers, with subscriber-level access and above, to extract data from password protected and private business details.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:NTechnical Details
What Changed in the Fix
Changes introduced in v1.53.2
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2025-9987 - Broadstreet Information Disclosure ## 1. Vulnerability Summary The Broadstreet plugin (<= 1.53.1) contains an information disclosure vulnerability in its AJAX handling logic. Specifically, the `get_sponsored_meta()` AJAX action (registered via `wp_ajax_…
Show full research plan
Exploitation Research Plan: CVE-2025-9987 - Broadstreet Information Disclosure
1. Vulnerability Summary
The Broadstreet plugin (<= 1.53.1) contains an information disclosure vulnerability in its AJAX handling logic. Specifically, the get_sponsored_meta() AJAX action (registered via wp_ajax_get_sponsored_meta and potentially wp_ajax_nopriv_get_sponsored_meta) fails to perform adequate authorization or visibility checks. This allows authenticated users (with Subscriber-level permissions or higher) to retrieve post metadata from posts that should be restricted, such as private posts or password-protected posts containing sensitive business details.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
get_sponsored_meta - Parameters:
action:get_sponsored_metapost_id(orid): The ID of the target post (inferred)._wpnonce: (Likely required if registered via standard WordPress AJAX patterns).
- Authentication: Subscriber-level access is required according to the description (CVSS suggests PR:N, so unauthenticated access should also be tested).
- Preconditions: A post exists that is either "Private" or "Password Protected" and contains metadata (custom fields).
3. Code Flow
Note: Broadstreet/Core.php was not provided in the source snippet, but the vulnerability is tied to the get_sponsored_meta action registered in the plugin's initialization.
- Initialization: The plugin initializes
Broadstreet_Coreinbroadstreet.php. - Hook Registration:
Broadstreet_Core(likely in a_register_ajaxorinitmethod) registers the hook:add_action('wp_ajax_get_sponsored_meta', array($this, 'get_sponsored_meta')); - Execution: When the AJAX action is called:
- The handler retrieves a
post_idfrom$_POSTor$_GET. - It calls
get_post_meta($post_id)or a similar function to fetch data. - Vulnerability: It fails to check if the current user has permission to read the post (e.g., via
current_user_can('read_post', $post_id)) or if the post is password protected (post_password_required($post_id)).
- The handler retrieves a
- Sink: The metadata is returned as a JSON response to the unauthorized requester.
4. Nonce Acquisition Strategy
To find the nonce and the correct variable names, we will use the browser_eval tool.
- Identify Script Localization: The plugin likely uses
wp_localize_scriptto pass a nonce to the frontend. - Search Strategy:
- Use
grep -r "wp_create_nonce" .to find the action string used for theget_sponsored_metanonce. - Use
grep -r "wp_localize_script" .to find the JavaScript object name.
- Use
- Common Patterns for Broadstreet:
- Potential JS object:
Broadstreetorbroadstreet_ajax. - Potential nonce key:
nonce.
- Potential JS object:
- Execution Steps:
- Create a page containing a Broadstreet widget or shortcode (e.g.,
[broadstreet_zone]) if one exists, to ensure the script is loaded. - Navigate to that page.
- Run:
browser_eval("window.Broadstreet?.nonce")(inferred) or inspect the page source forwp-admin/admin-ajax.phpreferences.
- Create a page containing a Broadstreet widget or shortcode (e.g.,
5. Exploitation Strategy
Step 1: Target Identification
Find a Post ID for a private or password-protected post. We will create one for testing.
Step 2: Information Extraction
Send an authenticated POST request to the AJAX endpoint.
Request Template:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=get_sponsored_meta&post_id=[TARGET_ID]&_wpnonce=[NONCE]
Step 3: Payload Probing
Since the exact parameter name for the post ID is inferred:
- Try
post_id. - Try
id. - Try
postID.
6. Test Data Setup
- Create Administrator User: To set up the sensitive data.
- Create Subscriber User: To act as the attacker.
- Create Protected Content:
- Create a new post.
- Set status to
privateor set a password. - Add sensitive custom fields (metadata) using WP-CLI:
wp post meta add [ID] secret_business_key "Confidential Information"wp post meta add [ID] bs_sponsored_data "Hidden Revenue Stats"
7. Expected Results
- A successful exploit will return a
200 OKstatus and a JSON body containing the metadata of the protected post. - Example response:
{"success": true, "data": {"secret_business_key": "Confidential Information", "bs_sponsored_data": "Hidden Revenue Stats"}}
8. Verification Steps
- WP-CLI Check: Verify the metadata exists on the post:
wp post meta list [ID] - Permission Check: Confirm the Subscriber user cannot see the post content normally:
browser_navigateto the post URL while logged in as Subscriber and verify a 404 or "Post not found" message. - Comparison: Compare the data returned by the AJAX request with the data retrieved via WP-CLI.
9. Alternative Approaches
- Unauthenticated Check: Test if
wp_ajax_nopriv_get_sponsored_metais registered. If so, attempt the request without the Subscriber cookies. - Bulk Extraction: If the
post_idparameter is missing or can be an array, try to extract metadata for multiple posts at once. - Parameter Mining: If
post_idfails, usegrepon the plugin directory to find the specific variable name used in theget_sponsored_metafunction withinCore.php.grep -rn "function get_sponsored_meta" -A 10
Summary
The Broadstreet plugin for WordPress is vulnerable to unauthorized information disclosure via the `get_sponsored_meta` AJAX action. This flaw allows authenticated attackers with Subscriber-level permissions to retrieve post metadata from private or password-protected posts, as the plugin fails to perform proper authorization or visibility checks on the requested post ID.
Security Fix
@@ -140,4 +140,4 @@ } } -define('BROADSTREET_VERSION', '1.53.1'); +define('BROADSTREET_VERSION', '1.53.2'); @@ -3,7 +3,7 @@ Plugin Name: Broadstreet Plugin URI: http://broadstreetads.com Description: Integrate Broadstreet business directory and adserving power into your site -Version: 1.53.1 +Version: 1.53.2 Tested up to: 6.9 Author: Broadstreet Author URI: http://broadstreetads.com @@ -3,7 +3,7 @@ Tags: broadstreet,local,publishers,hyperlocal,independent,news,business,directory Requires at least: 3.0 Tested up to: 6.9 -Stable tag: 1.53.1 +Stable tag: 1.53.2 Integrate Broadstreet adserving power into your site.
Exploit Outline
To exploit this vulnerability, an attacker first authenticates as a Subscriber-level user. They must then identify the ID of a target private or password-protected post. By locating the AJAX nonce (typically provided via localized scripts in the site's frontend), the attacker sends a POST request to /wp-admin/admin-ajax.php with the action parameter set to get_sponsored_meta and the target post_id. The application returns the full metadata associated with that post, bypassing access controls that should prevent visibility into restricted content.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.