Business Directory <= 6.4.19 - Missing Authorization
Description
The Business Directory Plugin – Easy Listing Directories for WordPress plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 6.4.19. This makes it possible for authenticated attackers, with Author-level access and above, to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=6.4.19Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2025-64630 ## 1. Vulnerability Summary **CVE-2025-64630** is a Missing Authorization vulnerability in the **Business Directory Plugin** (versions <= 6.4.19). The vulnerability allows authenticated users with **Author-level** permissions or higher to perform unauth…
Show full research plan
Exploitation Research Plan - CVE-2025-64630
1. Vulnerability Summary
CVE-2025-64630 is a Missing Authorization vulnerability in the Business Directory Plugin (versions <= 6.4.19). The vulnerability allows authenticated users with Author-level permissions or higher to perform unauthorized actions, likely related to listing management or directory configuration, due to insufficient capability checks in an AJAX handler or a specific administrative function.
In Business Directory Plugin, many operations are handled via a central AJAX dispatcher or specific wp_ajax_ hooks. The missing authorization implies that a function intended for Administrators (who have manage_options) is accessible to Authors because it either lacks a current_user_can() check or uses an insufficiently restrictive capability (like edit_posts).
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Authentication: Author-level credentials (username/password required).
- Vulnerable Action: (Inferred) An action related to modifying listing metadata, status, or featured levels, such as
wpbdp_admin_ajaxor a specific listing-flagging action. - Payload Parameters:
action: The specific AJAX action (e.g.,wpbdp_set_listing_featuredor similar).listing_id/post_id: The ID of a listing to modify.nonce: A security nonce required for the AJAX action.
- Preconditions: The attacker must have an account with the
Authorrole. The target listing should ideally belong to another user (e.g., the Administrator) to demonstrate unauthorized modification.
3. Code Flow
- Entry Point: The request hits
admin-ajax.phpwith a registeredaction. - Hook Registration: The plugin registers AJAX handlers in
includes/class-business-directory.phporincludes/admin/class-admin-listings.phpusingadd_action( 'wp_ajax_...' ). - Dispatching: The request is routed to a callback function (e.g.,
WPBDP_Admin_Listings::ajax_callback). - The Vulnerability: The callback function performs sensitive operations (like updating post meta or changing post status) without calling
current_user_can( 'manage_options' )or checking if the current user is the author of thelisting_idprovided in the request. - Sink: Functions like
update_post_meta(),wp_update_post(), or internal plugin methods likeWPBDP_Listing::set_flag()are executed.
4. Nonce Acquisition Strategy
Business Directory Plugin typically enqueues admin scripts that contain nonces in the wpbdp_admin or wpbdp_global JavaScript objects.
- Identify Script Localization: Search the source for
wp_localize_scriptto find the admin nonce key.- Likely Variable:
window.wpbdp_adminorwindow.wpbdp_global. - Likely Key:
nonce.
- Likely Variable:
- Access the Admin Dashboard: Log in as the Author user and navigate to the Business Directory section of the WordPress admin panel (
/wp-admin/edit.php?post_type=wpbdp_listing). - Extract Nonce:
// Use browser_eval to extract the nonce const nonce = window.wpbdp_admin?.nonce || window.wpbdp_global?.nonce; - Identify the Action String: In the plugin source, look for
check_ajax_referer( 'wpbdp-admin-ajax', ... )orwp_verify_nonce( ..., 'wpbdp-listing-flag' )to identify the correct nonce action context.
5. Exploitation Strategy
The goal is to demonstrate that an Author can modify a listing that they do not own (e.g., changing its "Featured" status or expiration).
Step-by-Step Plan:
- Setup Phase:
- Create an Administrator user.
- Create an Author user.
- As the Administrator, create a Business Directory listing (
post_type=wpbdp_listing). Record itsID.
- Authentication Phase:
- Log in to the WordPress site as the Author via the
browser_navigateand login tools.
- Log in to the WordPress site as the Author via the
- Nonce Extraction:
- Navigate to the listings page in the admin area:
/wp-admin/edit.php?post_type=wpbdp_listing. - Use
browser_evalto extract thewpbdp_admin.nonce.
- Navigate to the listings page in the admin area:
- Execution Phase:
- Use
http_requestto send a POST request toadmin-ajax.php. - Target Action (Likely Candidate):
wpbdp-listing-set-flagorwpbdp_admin_ajax. - Payload Example:
(Note: The exactPOST /wp-admin/admin-ajax.php HTTP/1.1 Content-Type: application/x-www-form-urlencoded action=wpbdp_admin_ajax&handler=listings__set_flag&listing_id=[ADMIN_LISTING_ID]&flag=featured&nonce=[EXTRACTED_NONCE]handlerandflagnames must be verified in the source code.)
- Use
6. Test Data Setup
- Users:
admin_user(Administrator)attacker_author(Author)
- Listing:
- Title: "Admin's Premium Listing"
- Author:
admin_user - Featured Status:
false(default)
- Plugin Config: Ensure Business Directory is active and the Author role has access to view the listings menu in the backend (default behavior).
7. Expected Results
- Response: The server returns a
200 OKwith a JSON body indicating success (e.g.,{"success": true}). - Effect: The listing belonging to the Administrator now has the "Featured" flag set (or its status changed), which the Author should not be able to perform.
8. Verification Steps
After the HTTP request, use WP-CLI to verify the state change:
# Check if the listing's featured status has changed in post meta
wp post meta get [ADMIN_LISTING_ID] _wpbdp[featured_level]
# Or check the listing flags
wp eval "echo WPBDP_Listing::get([ADMIN_LISTING_ID])->get_flag('featured');"
9. Alternative Approaches
If the wpbdp_admin_ajax dispatcher is not the vulnerability:
- Search for other AJAX actions:
grep -rn "wp_ajax_" . | grep "listing" - Look for status change handlers: Look for functions handling the "Published" to "Pending" or "Expired" transitions.
- Check for "Manual Renewal": Sometimes Authors can bypass payment or authorization for renewing listings they don't own by triggering renewal AJAX actions.
- Verify specific flags: If "featured" is protected, try "sticky", "verified", or modifying the "expiration date" metadata directly if an AJAX action allows
meta_keymanipulation.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.