Simple calendar for Elementor <= 1.6.6 - Missing Authorization to Unauthenticated Arbitrary Calendar Entry Deletion
Description
The Simple calendar for Elementor plugin for WordPress is vulnerable to Missing Authorization in all versions up to, and including, 1.6.6. This is due to missing capability checks on the `miga_ajax_editor_cal_delete` function that is hooked to the `miga_editor_cal_delete` AJAX action with both authenticated and unauthenticated access enabled. This makes it possible for unauthenticated attackers to delete arbitrary calendar entries by sending a request with a valid nonce and the calendar entry ID.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=1.6.6Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-1310 ## 1. Vulnerability Summary The **Simple calendar for Elementor** plugin (versions <= 1.6.6) contains a missing authorization vulnerability in its AJAX handling logic. Specifically, the function `miga_ajax_editor_cal_delete` is registered to both `wp_ajax…
Show full research plan
Exploitation Research Plan: CVE-2026-1310
1. Vulnerability Summary
The Simple calendar for Elementor plugin (versions <= 1.6.6) contains a missing authorization vulnerability in its AJAX handling logic. Specifically, the function miga_ajax_editor_cal_delete is registered to both wp_ajax_miga_editor_cal_delete and wp_ajax_nopriv_miga_editor_cal_delete hooks. This allows unauthenticated users to trigger the deletion of calendar entries. While a nonce check is present, the nonce is exposed to unauthenticated users on pages where the calendar or editor scripts are loaded, and there is no accompanying current_user_can() check to verify the user's permissions.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
miga_editor_cal_delete - Method: POST
- Parameters:
action:miga_editor_cal_deletenonce: A valid WordPress nonce (obtained via frontend script localization).id: The ID of the calendar entry to be deleted (likely a post ID).
- Authentication: Unauthenticated (via
wp_ajax_nopriv_hook). - Preconditions: The attacker must obtain a valid nonce, which is typically available on any page where the plugin's Elementor widget or shortcode is rendered.
3. Code Flow
- Hook Registration: The plugin registers the AJAX actions in the main plugin file or an initialization class:
add_action('wp_ajax_miga_editor_cal_delete', 'miga_ajax_editor_cal_delete'); add_action('wp_ajax_nopriv_miga_editor_cal_delete', 'miga_ajax_editor_cal_delete'); - Function Execution (
miga_ajax_editor_cal_delete):- The function is called with the
$_POSTdata. - It performs a nonce check:
check_ajax_referer('miga_calendar_nonce_action', 'nonce')(Action name inferred). - Crucially: It fails to check
current_user_can('edit_posts')or similar. - It retrieves the entry ID from
$_POST['id']. - It calls a deletion function, likely
wp_delete_post($id, true)or a custom database query via$wpdb.
- The function is called with the
4. Nonce Acquisition Strategy
The nonce is required for the check_ajax_referer call to pass. In WordPress plugins, these are almost always localized for JavaScript.
- Identify Script Localization: The plugin likely uses
wp_localize_scriptto pass the nonce to the frontend. - Shortcode/Widget: Identify the shortcode or Elementor widget that triggers the script. Based on the plugin name, look for
[miga_calendar]or similar (inferred). - Extraction Steps:
- Step 1: Create a public post/page containing the calendar widget.
- Step 2: Navigate to that page using
browser_navigate. - Step 3: Use
browser_evalto find the nonce in the global JavaScript scope. - Target Variable: Likely
miga_calendar_params.nonceormiga_ajax_obj.nonce(inferred). - Specific JS Check:
browser_eval("window.miga_calendar_params?.nonce || window.miga_calendar_vars?.nonce").
5. Exploitation Strategy
- Target Identification: Determine the ID of a calendar entry (Post ID) to delete.
- Nonce Extraction: Follow the acquisition strategy above to get a valid nonce for the
miga_editor_cal_deleteaction. - Payload Construction:
- URL:
http://[target-ip]/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=miga_editor_cal_delete&nonce=[NONCE]&id=[TARGET_ID]
- URL:
- Execution: Use the
http_requesttool to send the POST request. - Expected Response: A success code (e.g.,
1,true, or a JSON success message) and a 200 OK HTTP status.
6. Test Data Setup
- Create Calendar Entry: Use WP-CLI to create a dummy calendar entry. Assuming the plugin uses a Custom Post Type (CPT) named
miga_calendar(inferred):
Note: Capture the ID returned by this command.wp post create --post_type=miga_calendar --post_title="Target Event" --post_status=publish - Create Trigger Page: Create a page that includes the plugin's frontend component to ensure the nonce is generated and localized:
wp post create --post_type=page --post_title="Calendar Page" --post_status=publish --post_content='[miga_calendar]'
7. Expected Results
- The
http_requestshould return a response indicating the deletion was successful. - The calendar entry with the specified
idshould no longer exist in the database.
8. Verification Steps
- Verify Deletion via WP-CLI:
If the command returns nothing or an error, the post was successfully deleted.wp post exists [TARGET_ID] - Check Database Directly:
An empty result set confirms the deletion.wp db query "SELECT ID FROM wp_posts WHERE ID=[TARGET_ID]"
9. Alternative Approaches
- ID Brute Forcing: Since the vulnerability allows unauthenticated deletion, if the ID of an entry is unknown, an attacker could iterate through recent Post IDs to delete all calendar content.
- REST API Check: Check if the plugin registers a REST API endpoint for the same functionality, as missing authorization often extends across multiple entry points. Look for
register_rest_route. - Action String Guessing: If the nonce action string is not found in the global scope, check the page source for
check_ajax_referercalls in the plugin PHP files to identify the exact action name, then look for where that specific action's nonce is localized.
Summary
The Simple calendar for Elementor plugin for WordPress is vulnerable to unauthorized calendar entry deletion due to a missing capability check in the `miga_ajax_editor_cal_delete` function. Unauthenticated attackers can exploit this by obtaining a valid nonce from the frontend and sending a request to the AJAX endpoint with a specific calendar entry ID.
Vulnerable Code
// The AJAX function lacks a current_user_can() check and is registered to unauthenticated users add_action('wp_ajax_miga_editor_cal_delete', 'miga_ajax_editor_cal_delete'); add_action('wp_ajax_nopriv_miga_editor_cal_delete', 'miga_ajax_editor_cal_delete'); function miga_ajax_editor_cal_delete() { check_ajax_referer('miga_calendar_nonce_action', 'nonce'); $id = isset($_POST['id']) ? intval($_POST['id']) : 0; if ($id) { wp_delete_post($id, true); } wp_send_json_success(); wp_die(); }
Security Fix
@@ -20,6 +20,10 @@ function miga_ajax_editor_cal_delete() { check_ajax_referer('miga_calendar_nonce_action', 'nonce'); + if (!current_user_can('edit_posts')) { + wp_send_json_error('Unauthorized'); + } + $id = isset($_POST['id']) ? intval($_POST['id']) : 0; if ($id) { wp_delete_post($id, true);
Exploit Outline
To exploit this vulnerability, an attacker first identifies a page on the target site where the Simple calendar for Elementor widget or shortcode is present. By inspecting the page source or global JavaScript variables (e.g., window.miga_calendar_params), the attacker extracts a valid nonce intended for the 'miga_calendar_nonce_action'. The attacker then determines the ID of a calendar entry they wish to delete. Finally, the attacker sends an unauthenticated POST request to /wp-admin/admin-ajax.php with the parameters 'action=miga_editor_cal_delete', the extracted 'nonce', and the target 'id'. Because the plugin fails to verify the user's permissions, the server deletes the specified post.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.