CVE-2025-13920

WP Directory Kit <= 1.4.9 - Unauthenticated Email Exposure via wdk_public_action

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

Description

The WP Directory Kit plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 1.4.9 via the wdk_public_action AJAX handler. This makes it possible for unauthenticated attackers to extract email addresses for users with Directory Kit-specific user roles.

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<=1.4.9
PublishedJanuary 23, 2026
Last updatedJanuary 24, 2026
Affected pluginwpdirectorykit

What Changed in the Fix

Changes introduced in v1.5.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This vulnerability in the **WP Directory Kit** plugin (<= 1.4.9) allows unauthenticated attackers to extract sensitive user information, specifically email addresses, by abusing the `wdk_public_action` AJAX dispatcher to call the `treefieldid` method. The `treefieldid` function acts as a generic dat…

Show full research plan

This vulnerability in the WP Directory Kit plugin (<= 1.4.9) allows unauthenticated attackers to extract sensitive user information, specifically email addresses, by abusing the wdk_public_action AJAX dispatcher to call the treefieldid method. The treefieldid function acts as a generic database query builder for autocomplete/lookup fields and lacks sufficient access control or input validation to prevent querying the users table.

1. Vulnerability Summary

  • Vulnerability: Unauthenticated Sensitive Information Exposure (Email Addresses).
  • Vulnerable Component: Wdk_frontendajax::treefieldid method, accessed via the wdk_public_action AJAX handler.
  • Cause: The treefieldid method allows specifying a database model (table) and columns (attribute_id, attribute_value) to query. It uses user-supplied parameters to construct a SQL LIKE query without restricting which models (tables) or columns can be accessed.
  • Authentication: Unauthenticated (via wp_ajax_nopriv_wdk_public_action).

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: wdk_public_action
  • Vulnerable Method: treefieldid
  • HTTP Method: POST
  • Key Parameters:
    • wdk_controller: frontendajax (routes to Wdk_frontendajax class)
    • wdk_method: treefieldid
    • table: The model to query. In this plugin's architecture, user_m or agent_m are the likely targets for user data.
    • attribute_id: The column to use as the key (e.g., ID).
    • attribute_value: The column to expose (e.g., user_email).
    • search_term: The string to search for (e.g., @ to match all emails).
    • wdk_secure: A WordPress nonce for the action wdk_secure_treefieldid.

3. Code Flow

  1. Entry Point: An unauthenticated request is sent to admin-ajax.php with action=wdk_public_action.
  2. Dispatcher: The plugin's dispatcher (within the Winter MVC framework) receives wdk_controller=frontendajax and wdk_method=treefieldid. It instantiates Wdk_frontendajax and calls treefieldid().
  3. Nonce Check: treefieldid() calls check_ajax_referer('wdk_secure_treefieldid', 'wdk_secure'). This nonce is localized on public pages where the Directory Kit search or agent functionality is active.
  4. Query Construction:
    • The table parameter (e.g., user_m) is passed to $this->load->model($table).
    • $attr_val is taken from attribute_value (e.g., user_email).
    • $attr_search is taken from search_term (e.g., @).
    • A $where clause is built: ($id_part $attr_val_sql LIKE '%$attr_search%').
  5. Information Leak: The model executes the query against the WordPress database, and the results (containing the email addresses) are returned as a JSON object to the attacker.

4. Nonce Acquisition Strategy

The treefieldid method requires a nonce (wdk_secure_treefieldid). This nonce is localized by the plugin for use in its frontend search/autocomplete features.

  1. Identify Trigger: The nonce is typically localized when the [wdk_search] or [wdk_listings] shortcode is present on a page.
  2. Create Page: Use WP-CLI to create a public page containing the shortcode:
    wp post create --post_type=page --post_title="Directory Search" --post_status=publish --post_content='[wdk_search]'
    
  3. Extract Nonce:
    • Navigate to the newly created page using browser_navigate.
    • The plugin localizes its data into a global JavaScript object named wdk_frontend_obj.
    • Use browser_eval to extract the nonce:
      window.wdk_frontend_obj?.wdk_secure_treefieldid
      

5. Exploitation Strategy

Once the nonce is obtained, perform the following http_request:

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=wdk_public_action&wdk_controller=frontendajax&wdk_method
    
Research Findings
Static analysis — not yet PoC-verified

Summary

The WP Directory Kit plugin for WordPress is vulnerable to sensitive information exposure via the `treefieldid` method in the `Wdk_frontendajax` class. Unauthenticated attackers can exploit this by abusing a generic database query builder intended for autocomplete fields to extract sensitive user data, including email addresses, from the WordPress database.

Vulnerable Code

// application/controllers/Wdk_frontendajax.php line 111
public function treefieldid($output="", $atts=array(), $instance=NULL)
{
    check_ajax_referer('wdk_secure_treefieldid', 'wdk_secure');
    // ... (logic to extract parameters from $_POST)
    $table_name = $table = $parameters['table'];
    // ...
    $this->load->model($table);

---

// application/controllers/Wdk_frontendajax.php line 293
if(current_user_can('wdk_listings_manage'))
    $results[$ind_order]['value'] .= ' ('.wmvc_show_data('user_email', $row).')';

---

// application/controllers/Wdk_frontendajax.php line 333
if(current_user_can('wdk_listings_manage'))
    $data['curr_val'] .= ' ('.wmvc_show_data('user_email', $row).')'.' #'.wmvc_show_data($attr_id, $row);

Security Fix

--- /home/deploy/wp-safety.org/data/plugin-versions/wpdirectorykit/1.4.9/application/controllers/Wdk_frontendajax.php	2026-01-08 21:06:02.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/wpdirectorykit/1.5.0/application/controllers/Wdk_frontendajax.php	2026-03-10 20:39:26.000000000 +0000
@@ -293,8 +293,8 @@
 					$results[$ind_order]['value'] = $level_gen
 												.'#'.wmvc_show_data($attr_id, $row).', '.wmvc_show_data('display_name', $row);
 
-					if(current_user_can('wdk_listings_manage'))
-						$results[$ind_order]['value'] .= ' ('.wmvc_show_data('user_email', $row).')';
+					//if(current_user_can('wdk_listings_manage'))
+					//	$results[$ind_order]['value'] .= ' ('.wmvc_show_data('user_email', $row).')';
 				} elseif($table == 'icons_list') {
 					$results[$ind_order]['key'] = $row;
 					if(defined('ELEMENTOR_ASSETS_URL')){
@@ -333,8 +333,6 @@
 				$data['curr_val'] = $level_gen
 											.wmvc_show_data('display_name', $row);
 				
-				if(current_user_can('wdk_listings_manage'))
-					$data['curr_val'] .= ' ('.wmvc_show_data('user_email', $row).')'.' #'.wmvc_show_data($attr_id, $row);
 			} else {
 				$data['curr_val'] = $level_gen
 							.esc_html__(wmvc_show_data(wmvc_show_data('attribute_value', $parameters), $row), 'wpdirectorykit');

Exploit Outline

1. Identify a public-facing page on the target site that uses WP Directory Kit shortcodes (e.g., [wdk_search] or [wdk_listings]). 2. Extract the `wdk_secure_treefieldid` nonce from the page source, typically found in the `wdk_frontend_obj` global JavaScript variable. 3. Construct an unauthenticated POST request to `/wp-admin/admin-ajax.php` with the `action` parameter set to `wdk_public_action`. 4. Set the `wdk_controller` to `frontendajax` and `wdk_method` to `treefieldid`. 5. Include the extracted nonce in the `wdk_secure` parameter. 6. Provide parameters to target user data: set `table` to `user_m` (or `agent_m`), `attribute_id` to `ID`, `attribute_value` to `user_email`, and `search_term` to a wildcard character like `@`. 7. The server response will return a JSON object containing the results of the database query, including the exposed email addresses.

Check if your site is affected.

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