Court Reservation <= 1.10.11 - Missing Authorization
Description
The Court Reservation plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.10.11. This makes it possible for unauthenticated attackers to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=1.10.11This research plan outlines the steps to investigate and exploit **CVE-2026-39675**, a Missing Authorization vulnerability in the **Court Reservation** plugin for WordPress. ### 1. Vulnerability Summary The **Court Reservation** plugin suffers from a missing capability check in one or more of its A…
Show full research plan
This research plan outlines the steps to investigate and exploit CVE-2026-39675, a Missing Authorization vulnerability in the Court Reservation plugin for WordPress.
1. Vulnerability Summary
The Court Reservation plugin suffers from a missing capability check in one or more of its AJAX handlers registered via wp_ajax_nopriv_*. This allows unauthenticated attackers to trigger sensitive functions—such as modifying, deleting, or creating reservations—that should be restricted to authenticated users or administrators. The vulnerability exists because the developer likely used check_ajax_referer() (which only validates the request's origin/authenticity) but failed to implement current_user_can() (which validates the user's permissions).
2. Attack Vector Analysis
- Endpoint:
http://<target>/wp-admin/admin-ajax.php - Method: POST
- Action: Likely
cr_cancel_reservation,cr_delete_reservation, orcr_save_reservation(inferred from plugin functionality). - Parameter:
action,reservation_id(or similar), and anonce. - Authentication: Unauthenticated (leveraging
wp_ajax_nopriv_hooks).
3. Code Flow (Inferred)
- Initialization: The plugin registers AJAX hooks in a main class or
includes/class-court-reservation-ajax.php(inferred).add_action( 'wp_ajax_nopriv_cr_cancel_reservation', array( $this, 'ajax_cancel_reservation' ) ); - Entry Point: The
ajax_cancel_reservationfunction is called. - Vulnerable Path:
- The function calls
check_ajax_referer( 'cr_nonce', 'security' );. - It retrieves
$_POST['reservation_id']. - CRITICAL GAP: It fails to check
if ( ! current_user_can( 'manage_options' ) )or verify if the current unauthenticated session owns the reservation.
- The function calls
- Sink: The function proceeds to update the database via
$wpdb->update()orwp_delete_post(), effectively cancelling a reservation unauthorized.
4. Nonce Acquisition Strategy
To exploit wp_ajax_nopriv handlers, we must obtain a valid nonce generated for an unauthenticated user (UID 0).
- Identify Shortcode: Search for shortcodes that render the reservation interface:
grep -r "add_shortcode" .(Commonly[court_reservation]or[cr_calendar]). - Locate Nonce Variable: Search for where the nonce is passed to JavaScript:
grep -r "wp_localize_script" .- Look for a handle like
cr_script_varsorcourt_reservation_params. - Identify the key (e.g.,
security,nonce, orcr_nonce).
- Look for a handle like
- Create Trigger Page:
wp post create --post_type=page --post_status=publish --post_title="Reservations" --post_content='[court_reservation]' - Extract Nonce via Browser:
Navigate to the new page and usebrowser_evalto grab the nonce from the global window object.- Example JavaScript:
window.cr_script_vars?.nonceorwindow.cr_params?.security.
- Example JavaScript:
5. Exploitation Strategy
Once the action name and nonce are identified, follow these steps:
- Target Identification: Confirm the specific AJAX action and the ID of the reservation to target.
- Request Construction: Use the
http_requesttool.- URL:
http://<target>/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=[VULNERABLE_ACTION]&security=[NONCE]&reservation_id=[TARGET_ID]
- URL:
- Execution: Send the request and analyze the JSON response (usually
{"success":true}).
6. Test Data Setup
- Install Plugin: Ensure
court-reservationversion <= 1.10.11 is active. - Create Admin:
wp user create victim admin@example.com --role=administrator --user_pass=password. - Create Sample Data: Create a reservation as the administrator (or via the plugin's legitimate frontend if available) so there is an ID to target.
- If reservations are Custom Post Types (CPT):
wp post create --post_type=cr_reservation --post_title="Victim Booking" --post_status=publish.
- If reservations are Custom Post Types (CPT):
- Identify ID:
wp post list --post_type=cr_reservationto find the ID.
7. Expected Results
- Response: The server returns a
200 OKwith a body indicating success (e.g.,1,{"success":true}, or a success message). - State Change: The targeted reservation status is changed (e.g., from 'confirmed' to 'cancelled') or the record is deleted entirely from the database.
8. Verification Steps
- Check Database:
wp db query "SELECT post_status FROM wp_posts WHERE ID = [TARGET_ID]" # OR if custom table: wp db query "SELECT status FROM wp_court_reservations WHERE id = [TARGET_ID]" - Confirm Status: Verify the status reflects the unauthorized action (e.g.,
cancelledortrash).
9. Alternative Approaches
- Information Disclosure: If the missing authorization is in a "fetch" action (e.g.,
cr_get_reservation_details), the exploit results in Sensitive Data Exposure rather than data modification. - ID Brute Forcing: If specific IDs are unknown, unauthenticated attackers can iterate through integer
reservation_idvalues to mass-cancel bookings. - Missing Nonce: Check if the function even calls
check_ajax_referer. If it doesn't, thenonceacquisition step can be skipped entirely, allowing for a direct POST attack. Look for:grep -r "add_action.*wp_ajax_nopriv" . -A 20and check ifcheck_ajax_refereris present in the callback.
Summary
The Court Reservation plugin for WordPress suffers from a missing authorization check in its AJAX handlers registered for unauthenticated users. This allows unauthenticated attackers to perform unauthorized actions, such as cancelling or deleting reservations, by leveraging a publicly accessible nonce.
Vulnerable Code
// Inferred from registration of hooks in the plugin add_action( 'wp_ajax_nopriv_cr_cancel_reservation', array( $this, 'ajax_cancel_reservation' ) ); --- // Inferred vulnerable handler logic from research plan public function ajax_cancel_reservation() { check_ajax_referer( 'cr_nonce', 'security' ); $reservation_id = intval( $_POST['reservation_id'] ); // CRITICAL GAP: It fails to check if ( ! current_user_can( 'manage_options' ) ) or verify ownership $result = $this->cancel_reservation( $reservation_id ); if ( $result ) { wp_send_json_success(); } }
Security Fix
@@ -10,6 +10,10 @@ public function ajax_cancel_reservation() { check_ajax_referer( 'cr_nonce', 'security' ); + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( 'Unauthorized access.', 403 ); + } + $reservation_id = intval( $_POST['reservation_id'] ); $result = $this->cancel_reservation( $reservation_id );
Exploit Outline
1. Nonce Acquisition: Locate a public page containing the [court_reservation] shortcode. Inspect the page source or use a browser console to find the localized script variables (e.g., cr_script_vars.nonce or similar) used for AJAX authentication. 2. Parameter Identification: Determine the ID of the reservation target and the specific AJAX action used for modification/deletion (e.g., cr_cancel_reservation). 3. Attack Execution: Perform an unauthenticated POST request to /wp-admin/admin-ajax.php. The payload must include the 'action' (the vulnerable hook), the extracted 'security' (nonce), and the 'reservation_id'. 4. Result: Since the backend handler fails to verify user permissions (current_user_can), the plugin executes the sensitive action despite the attacker lacking the required privileges.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.