CVE-2026-39566

DirectoryPress <= 3.6.26 - Unauthenticated Information Exposure

mediumExposure of Sensitive Information to an Unauthorized Actor
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
3.6.27
Patched in
44d
Time to patch

Description

The DirectoryPress – Business Directory And Classified Ad Listing plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 3.6.26. This makes it possible for unauthenticated attackers to extract sensitive user or configuration data.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.6.26
PublishedMarch 23, 2026
Last updatedMay 5, 2026
Affected plugindirectorypress

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan focuses on identifying and exploiting an unauthenticated information exposure vulnerability in the **DirectoryPress** plugin (<= 3.6.26). Since the source code is not provided, this plan incorporates a discovery phase to ground the exploit in the actual plugin identifiers. --- #…

Show full research plan

This research plan focuses on identifying and exploiting an unauthenticated information exposure vulnerability in the DirectoryPress plugin (<= 3.6.26). Since the source code is not provided, this plan incorporates a discovery phase to ground the exploit in the actual plugin identifiers.


1. Vulnerability Summary

The DirectoryPress plugin for WordPress is vulnerable to Sensitive Information Exposure due to an inadequately protected AJAX or REST API endpoint. Unauthenticated attackers can trigger specific actions that return sensitive data such as user metadata (emails, names, potentially password hashes) or plugin configuration settings (API keys, internal paths, or database prefixes). The flaw typically resides in wp_ajax_nopriv_ handlers that lack both current_user_can() checks and proper output filtering.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php (most likely) or a custom REST route under wp-json/directorypress/v1/.
  • Vulnerable Action: Likely directorypress_get_users, directorypress_get_listing_owners, or directorypress_export_data (inferred).
  • Parameter: action (for AJAX) or a specific GET/POST parameter for data filtering.
  • Authentication: None (Unauthenticated).
  • Preconditions: The plugin must be active. A valid nonce may be required if the handler calls check_ajax_referer().

3. Code Flow (Inferred)

  1. Registration: The plugin registers an AJAX action for unauthenticated users in a core file like includes/classes/class-ajax.php:
    add_action('wp_ajax_nopriv_VULNERABLE_ACTION', array($this, 'handler_function'));
  2. Request: An unauthenticated user sends a POST/GET request to admin-ajax.php with action=VULNERABLE_ACTION.
  3. Handler Execution: The handler_function is called. It likely performs a query using $wpdb or get_users() without checking for administrative capabilities.
  4. Information Leak: The handler returns the raw results via wp_send_json() or echo, which contains sensitive fields not intended for public view.

4. Nonce Acquisition Strategy

DirectoryPress typically localizes its AJAX settings into the frontend.

  1. Identify Shortcode: Locate a shortcode that initializes the directory UI (e.g., [directorypress_listings] or [directorypress_map]).
  2. Create Trigger Page:
    wp post create --post_type=page --post_title="Directory" --post_status=publish --post_content='[directorypress_listings]'
  3. Find Localization Key: In the browser, the plugin likely uses wp_localize_script to output a variable such as directorypress_js_obj or dp_ajax_vars.
  4. Extract Nonce via browser_eval:
    • Navigate to the created page.
    • Run: browser_eval("window.directorypress_js_obj?.nonce") or browser_eval("window.dp_ajax_vars?.ajax_nonce").
  5. Verify Action Match: Compare the action name found in the wp_ajax_nopriv_ registration with the nonce action string used in wp_create_nonce(). If the verify call is check_ajax_referer('directorypress_ajax', 'nonce'), the nonce must match the 'directorypress_ajax' action.

5. Exploitation Strategy

This plan targets a likely candidate for unauthenticated exposure: the user/listing owner data fetcher.

Step 1: Discovery (Internal Container Only)

Search the plugin directory to find the exact action name:

grep -r "wp_ajax_nopriv_" /var/www/html/wp-content/plugins/directorypress/

Assume the found action is directorypress_get_users_details (inferred).

Step 2: Nonce Extraction

Use the browser_navigate and browser_eval tools to grab the nonce from the localized script on the page created in the Setup section.

Step 3: Trigger Information Exposure

Send an unauthenticated request to the AJAX endpoint.

  • Method: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=directorypress_get_users_details&nonce=[EXTRACTED_NONCE]&limit=100
    

Step 4: Analyze Response

A successful exploit will return a JSON object containing user records. Inspect for:

  • user_email
  • user_login
  • display_name
  • user_registered
  • Any meta_value containing sensitive data.

6. Test Data Setup

Before exploitation, create a "victim" user with a recognizable email and meta data:

  1. Create Victim: wp user create victim victim@example.com --role=subscriber --user_pass=password123
  2. Add Sensitive Meta: wp usermeta update 2 secret_key "SECRET_INTERNAL_VALUE_99"
  3. Create Plugin Page: Place the main directory shortcode on a page to ensure nonces/scripts are loaded.
    wp post create --post_type=page --post_status=publish --post_content='[directorypress_listings]'

7. Expected Results

  • Success: An HTTP 200 response with a JSON body.
  • Data Found: The response contains "user_email": "victim@example.com" and potentially the "secret_key": "SECRET_INTERNAL_VALUE_99" or other internal configuration data.
  • Failure: An HTTP 403 response (nonce failure) or 0/empty response (capability check working).

8. Verification Steps

  1. Verify the leaked data matches the output of WP-CLI:
    wp user list --fields=ID,user_login,user_email
  2. Check if sensitive configuration was leaked by comparing with:
    wp option get directorypress_settings

9. Alternative Approaches

If the admin-ajax.php endpoint is properly protected, check for:

  1. REST API Discovery: Query http://localhost:8080/wp-json/wp/v2/users. Some directory plugins inadvertently re-enable user endpoints or add custom routes like /wp-json/directorypress/v1/data/ that ignore the "Discourage search engines" or "Privacy" settings.
  2. Debug Log Exposure: Check for wp-content/uploads/directorypress/logs/ or similar paths if the plugin has a custom logging feature.
  3. CSV Export: Look for actions like directorypress_csv_export. Try accessing it directly via admin-ajax.php?action=directorypress_csv_export to see if it generates a downloadable file without a session check.

Check if your site is affected.

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