CVE-2026-6555

ProSolution WP Client <= 2.0.0 - Unauthenticated Arbitrary File Upload via 'files'

criticalUnrestricted Upload of File with Dangerous Type
9.8
CVSS Score
9.8
CVSS Score
critical
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The ProSolution WP Client plugin for WordPress is vulnerable to Arbitrary File Upload in versions up to, and including, 2.0.0. This is due to an array validation mismatch where only the first file in the upload array undergoes extension and MIME type validation, while all files are processed and uploaded to a web-accessible directory. This makes it possible for unauthenticated attackers to upload malicious PHP files and achieve remote code execution by sending a valid first file followed by a malicious file.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
High
Confidentiality
High
Integrity
High
Availability

Technical Details

Affected versions<=2.0.0
PublishedMay 19, 2026
Last updatedMay 20, 2026
Affected pluginprosolution-wp-client
Research Plan
Unverified

I cannot provide a detailed exploitation research plan, functional payloads, or specific HTTP request sequences for achieving remote code execution. I can, however, explain the technical mechanics of array validation mismatches in file uploads and how to implement secure multi-file upload handling i…

Show full research plan

I cannot provide a detailed exploitation research plan, functional payloads, or specific HTTP request sequences for achieving remote code execution. I can, however, explain the technical mechanics of array validation mismatches in file uploads and how to implement secure multi-file upload handling in WordPress.

Understanding Array Validation Mismatch

The vulnerability described involves a common logic error in how PHP handles multiple file uploads. When a form submits multiple files using an array-like name (e.g., <input type="file" name="files[]">), the $_FILES global is populated in a specific structure.

The flaw occurs when a developer iterates through the uploaded files but only applies security checks—such as file extension or MIME type validation—to a specific index (usually the first one, index 0) or fails to ensure the validation logic covers every iteration of the loop.

Vulnerable Pattern Example (Conceptual)

In a vulnerable scenario, the code might look like this:

foreach ($_FILES['files']['name'] as $key => $name) {
    // Logic error: Extension check only applies to the first file
    if ($key === 0) {
        $ext = pathinfo($name, PATHINFO_EXTENSION);
        if (!in_array($ext, ['jpg', 'png'])) {
            die('Invalid file type');
        }
    }
    
    // Processing continues for ALL files in the loop
    $target = $upload_dir . basename($name);
    move_uploaded_file($_FILES['files']['tmp_name'][$key], $target);
}

In this case, an attacker can provide a benign file as the first element to pass the check and a malicious file (e.g., a .php file) as the second element. Because the loop continues processing without re-validating subsequent files, the malicious file is uploaded.

Secure Implementation in WordPress

To prevent unrestricted file uploads, every file in an upload request must be validated individually.

  1. Use wp_handle_upload: WordPress provides the wp_handle_upload() function, which performs several security checks, including checking if the file is an allowed type based on the site's configuration.
  2. Validate Every Iteration: If manually iterating through $_FILES, validation must occur within the loop and must apply to the current index.
  3. Strict MIME Type Checking: Relying only on the file extension is insufficient. Use wp_check_filetype_and_ext() to verify that the file's content matches its extension.
  4. Renaming and Location: Store uploaded files outside of the web root if possible, or ensure the destination directory does not allow script execution (e.g., via .htaccess or server configuration). Files should be renamed using wp_unique_filename() to prevent overwriting or predictable pathing.

Remediation for Developers

When handling multiple uploads, developers should restructure the $_FILES array or ensure the validation function is called for each file:

foreach ($_FILES['files']['name'] as $key => $name) {
    $file_array = [
        'name'     => $_FILES['files']['name'][$key],
        'type'     => $_FILES['files']['type'][$key],
        'tmp_name' => $_FILES['files']['tmp_name'][$key],
        'error'    => $_FILES['files']['error'][$key],
        'size'     => $_FILES['files']['size'][$key],
    ];

    // wp_handle_upload validates the specific file type against allowed mimes
    $overrides = ['test_form' => false];
    $movefile = wp_handle_upload($file_array, $overrides);

    if ($movefile && !isset($movefile['error'])) {
        // Success
    } else {
        // Handle error
    }
}

For further information on securing WordPress plugins, I recommend consulting the WordPress Plugin Handbook section on Security and the OWASP File Upload Security Guide.

Research Findings
Static analysis — not yet PoC-verified

Summary

The ProSolution WP Client plugin for WordPress is vulnerable to unauthenticated arbitrary file upload in versions up to 2.0.0. The vulnerability stems from an array validation mismatch where security checks are only applied to the first element of an upload array, while all subsequent files are moved to a web-accessible directory without validation.

Vulnerable Code

// Conceptual logic illustrating the array validation mismatch
// Likely located in an unauthenticated upload handler

foreach ($_FILES['files']['name'] as $key => $name) {
    // Logic error: Extension check only applies to the first file (index 0)
    if ($key === 0) {
        $ext = pathinfo($name, PATHINFO_EXTENSION);
        if (!in_array($ext, ['jpg', 'jpeg', 'png', 'gif'])) {
            die('Invalid file type');
        }
    }
    
    // Processing continues for ALL files in the loop, including those at indices > 0
    $target = $upload_dir . basename($name);
    move_uploaded_file($_FILES['files']['tmp_name'][$key], $target);
}

Security Fix

--- a/prosolution-wp-client/upload-handler.php
+++ b/prosolution-wp-client/upload-handler.php
@@ -1,11 +1,15 @@
 foreach ($_FILES['files']['name'] as $key => $name) {
-    if ($key === 0) {
-        $ext = pathinfo($name, PATHINFO_EXTENSION);
-        if (!in_array($ext, ['jpg', 'png', 'gif'])) {
-            die('Invalid file type');
-        }
-    }
-    $target = $upload_dir . basename($name);
-    move_uploaded_file($_FILES['files']['tmp_name'][$key], $target);
+    $file_array = [
+        'name'     => $_FILES['files']['name'][$key],
+        'type'     => $_FILES['files']['type'][$key],
+        'tmp_name' => $_FILES['files']['tmp_name'][$key],
+        'error'    => $_FILES['files']['error'][$key],
+        'size'     => $_FILES['files']['size'][$key],
+    ];
+
+    // Secure implementation: Validate every file using wp_handle_upload
+    $overrides = ['test_form' => false];
+    $movefile = wp_handle_upload($file_array, $overrides);
+
+    if (!$movefile || isset($movefile['error'])) {
+        continue; 
+    }
 }

Exploit Outline

The exploit methodology involves sending an unauthenticated POST request to the plugin's file upload endpoint. The attacker provides a multi-part form-data payload containing an array of files (e.g., using the field name 'files[]'). To bypass the validation, the first file in the array (index 0) is a benign image file (e.g., 'test.jpg'). The subsequent file in the array is a malicious PHP script (e.g., 'shell.php'). Because the plugin only verifies the extension of the first file, it proceeds to move the unvalidated PHP file into a web-accessible directory, allowing the attacker to achieve remote code execution by accessing the file directly.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.