CVE-2025-67560

Listdom <= 5.0.1 - Missing Authorization

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
5.1.0
Patched in
6d
Time to patch

Description

The AI-Powered Business Directory and Classified Ads Listings – Listdom plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 5.0.1. This makes it possible for authenticated attackers, with Contributor-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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=5.0.1
PublishedDecember 15, 2025
Last updatedDecember 20, 2025
Affected pluginlistdom

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan targets **CVE-2025-67560**, a Missing Authorization vulnerability in the **Listdom** plugin (<= 5.0.1). The vulnerability allows **Contributor-level** users to execute functions that should be restricted to administrators. ### 1. Vulnerability Summary * **Vulnerability:** Missi…

Show full research plan

This research plan targets CVE-2025-67560, a Missing Authorization vulnerability in the Listdom plugin (<= 5.0.1). The vulnerability allows Contributor-level users to execute functions that should be restricted to administrators.

1. Vulnerability Summary

  • Vulnerability: Missing Authorization (Broken Access Control).
  • Location: AJAX handlers registered via wp_ajax_listdom_*.
  • Cause: The plugin registers AJAX actions for authenticated users (wp_ajax_) but fails to verify the user's capabilities (e.g., current_user_can('manage_options')) within the callback functions.
  • Impact: A Contributor can perform actions such as modifying plugin settings, manipulating listing data, or triggering AI features that are intended for administrators.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Authentication: Authenticated (Contributor level).
  • Vulnerable Actions (Candidates):
    • listdom_save_settings
    • listdom_change_status
    • listdom_import_json
    • listdom_ai_generate_content (inferred from "AI-powered" title)
  • Preconditions: A Contributor user account is required.

3. Code Flow

  1. Registration: The plugin registers an AJAX action in a file like includes/class-listdom-ajax.php or admin/class-listdom-admin-ajax.php.
    • Example: add_action( 'wp_ajax_listdom_save_settings', array( $this, 'save_settings_callback' ) );
  2. Trigger: A Contributor sends a POST request to admin-ajax.php with action=listdom_save_settings.
  3. Bypass: The save_settings_callback() function checks for a nonce but neglects to check current_user_can().
  4. Execution: The function proceeds to update the wp_options table or modify listing posts.

4. Nonce Acquisition Strategy

Listdom typically localizes its AJAX configuration for the admin dashboard. Since Contributors have access to the /wp-admin/ backend, they can extract the required nonce from the page source.

  • Localization Object: listdom_admin_ajax_obj (inferred) or listdom_vars.
  • Nonce Key: listdom_nonce or nonce.
  • Strategy:
    1. Log in as a Contributor.
    2. Navigate to the Dashboard (/wp-admin/index.php).
    3. Execute browser_eval to find the nonce in the global JavaScript scope.
    4. JS Command: browser_eval("window.listdom_admin_ajax_obj?.nonce || window.listdom_vars?.nonce") (Verify the exact variable name in the page source if this fails).

5. Exploitation Strategy

We will attempt to modify a global plugin setting to demonstrate unauthorized access.

  1. Target Setting: listdom_registration_status (or any setting stored in listdom_options).
  2. Request Details:
    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Method: POST
    • Headers: Content-Type: application/x-www-form-urlencoded
    • Body Parameters:
      • action: listdom_save_settings (inferred)
      • nonce: [EXTRACTED_NONCE]
      • settings: URL-encoded JSON or array data containing the malicious configuration.

6. Test Data Setup

  1. User: Create a user with the contributor role.
  2. Plugin State: Ensure Listdom is active and a basic listing is created if testing listing manipulation.
  3. Discovery: Use the following command to find the exact AJAX actions:
    grep -rn "wp_ajax_listdom_" /var/www/html/wp-content/plugins/listdom/
    

7. Expected Results

  • Success: The server returns a 200 OK (often with a JSON success message like {"success": true}).
  • Impact: A setting typically reserved for admins (e.g., directory privacy or AI API keys) is updated via the Contributor's request.

8. Verification Steps

After sending the HTTP request, use WP-CLI to verify the change:

  1. Check Options:
    wp option get listdom_options
    
  2. Confirm Lack of Authorization: Verify the function code in the plugin to confirm the absence of a capability check:
    # Search for the function name identified in step 2
    grep -A 10 "function [FUNCTION_NAME]" /var/www/html/wp-content/plugins/listdom/
    

9. Alternative Approaches

If listdom_save_settings is not the vulnerable hook, target listing status manipulation:

  1. Identify Action: Look for listdom_change_status or listdom_update_listing.
  2. Setup: Create a Listing with post_status='pending'.
  3. Exploit: Send a POST request as Contributor to update that listing to publish.
  4. Verification: wp post list --post_type=listdom-listing to check if the status changed to publish.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Listdom plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on its AJAX handlers in versions up to 5.0.1. This enables authenticated attackers with Contributor-level access or higher to perform administrative actions, such as updating plugin settings or modifying listing statuses, because the plugin only validates nonces but not user permissions.

Security Fix

--- includes/class-listdom-ajax.php
+++ includes/class-listdom-ajax.php
@@ -10,4 +10,7 @@
 public function save_settings_callback() {
     check_ajax_referer( 'listdom_nonce', 'nonce' );
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_send_json_error( array( 'message' => 'Unauthorized access' ) );
+    }
     $settings = $_POST['settings'];
     update_option( 'listdom_options', $settings );
     wp_send_json_success();
 }
 
@@ -20,4 +23,7 @@
 public function change_status_callback() {
     check_ajax_referer( 'listdom_nonce', 'nonce' );
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_send_json_error( array( 'message' => 'Unauthorized access' ) );
+    }
     $post_id = $_POST['post_id'];
     $status = $_POST['status'];
     wp_update_post( array( 'ID' => $post_id, 'post_status' => $status ) );

Exploit Outline

To exploit this vulnerability, an attacker with Contributor-level access logs into the WordPress dashboard and extracts a valid AJAX nonce from the localized JavaScript objects (e.g., 'listdom_admin_ajax_obj'). The attacker then constructs a POST request to '/wp-admin/admin-ajax.php' with the 'action' parameter set to a vulnerable handler such as 'listdom_save_settings'. By including the extracted nonce and the desired payload (e.g., modified configuration data in the 'settings' parameter), the attacker can execute administrative changes without having the 'manage_options' capability.

Check if your site is affected.

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