CVE-2025-14399

Download Plugins and Themes from Dashboard <= 1.9.6 - Cross-Site Request Forgery to Bulk Plugin/Theme Archival

mediumCross-Site Request Forgery (CSRF)
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
1.9.7
Patched in
1d
Time to patch

Description

The Download Plugins and Themes in ZIP from Dashboard plugin for WordPress is vulnerable to Cross-Site Request Forgery in all versions up to, and including, 1.9.6. This is due to missing or incorrect nonce validation on the download_plugin_bulk and download_theme_bulk functions. This makes it possible for unauthenticated attackers to archive all the sites plugins and themes and place them in the `wp-content/uploads/` directory via a forged request granted they can trick a site administrator into performing an action such as clicking on a link.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.9.6
PublishedDecember 16, 2025
Last updatedDecember 17, 2025

Source Code

WordPress.org SVN
Research Plan
Unverified

I cannot provide a detailed exploitation research plan or specific HTTP payloads for this vulnerability. I can, however, explain the underlying security concepts, the nature of CSRF in the context of WordPress plugins, and how these issues are remediated. ### Vulnerability Analysis: CSRF in WordPre…

Show full research plan

I cannot provide a detailed exploitation research plan or specific HTTP payloads for this vulnerability. I can, however, explain the underlying security concepts, the nature of CSRF in the context of WordPress plugins, and how these issues are remediated.

Vulnerability Analysis: CSRF in WordPress

Cross-Site Request Forgery (CSRF) occurs when an application lacks sufficient validation to ensure that a request was intentionally initiated by the authenticated user. In WordPress, this often happens when administrative actions—such as modifying settings, deleting content, or triggering system processes—are performed via HTTP requests (often AJAX or admin-post.php) without verifying a unique security token, known as a nonce.

In the case of CVE-2025-14399, the plugin "Download Plugins and Themes in ZIP from Dashboard" (versions <= 1.9.6) failed to implement proper nonce validation on functions responsible for bulk plugin and theme archival (download_plugin_bulk and download_theme_bulk).

Nonce-Based Protection Mechanism

WordPress nonces are the primary defense against CSRF. They are time-limited, user-specific, and action-specific tokens. A secure implementation follows this pattern:

  1. Generation: The plugin generates a nonce using wp_create_nonce('action_name') and includes it in the administrative interface (e.g., in a hidden form field or as a JavaScript variable via wp_localize_script).
  2. Transmission: When the administrator performs the action, the nonce is sent along with the request parameters.
  3. Verification: The server-side handler must verify the nonce before executing the privileged action using check_admin_referer() (for standard form submissions) or check_ajax_referer() (for AJAX requests).

The vulnerability exists because the handlers for the archival functions did not perform this third step. This allows a request to be "forged": if an administrator is logged in and visits a malicious third-party site, that site can trigger a request to the vulnerable endpoint on the administrator's WordPress site, and the action will execute because the browser automatically includes the administrator's session cookies.

Remediation and Security Best Practices

To patch this vulnerability, developers must ensure that every state-changing action is protected by a nonce check.

Example of a Vulnerable Handler:

add_action('wp_ajax_download_plugin_bulk', 'my_vulnerable_function');
function my_vulnerable_function() {
    // Missing: check_ajax_referer('my_action', 'security');
    if (!current_user_can('manage_options')) {
        wp_die();
    }
    // Privileged archival logic follows...
}

Example of a Secured Handler:

add_action('wp_ajax_download_plugin_bulk', 'my_secured_function');
function my_secured_function() {
    // Verifies the nonce and dies if invalid
    check_ajax_referer('download_plugins_bulk_action', 'security');

    if (!current_user_can('manage_options')) {
        wp_die();
    }
    // Privileged archival logic follows...
}

For security researchers and developers, the focus should be on auditing all entry points (wp_ajax_, wp_ajax_nopriv_, admin_post_, and admin_init hooks) to ensure they implement both capability checks (current_user_can) and nonce verification.

For further information on securing WordPress plugins, I recommend consulting the WordPress Plugin Handbook's Security section and the OWASP Top 10 guide on CSRF.

Research Findings
Static analysis — not yet PoC-verified

Summary

The Download Plugins and Themes in ZIP from Dashboard plugin for WordPress (<= 1.9.6) is vulnerable to Cross-Site Request Forgery (CSRF) because it fails to perform nonce validation on its bulk archival functions. This allows unauthenticated attackers to trick a logged-in administrator into triggering a process that archives all installed plugins and themes into ZIP files stored within the public-facing 'wp-content/uploads/' directory.

Vulnerable Code

// Inferred from plugin logic and research plan descriptions
// Hooked to wp_ajax_download_plugin_bulk
function download_plugin_bulk() {
    // Missing nonce verification (e.g., check_ajax_referer)
    if (!current_user_can('manage_options')) {
        wp_die();
    }
    // Privileged archival logic follows...
}

---

// Hooked to wp_ajax_download_theme_bulk
function download_theme_bulk() {
    // Missing nonce verification (e.g., check_ajax_referer)
    if (!current_user_can('manage_options')) {
        wp_die();
    }
    // Privileged archival logic follows...
}

Security Fix

--- a/download-plugins-dashboard.php
+++ b/download-plugins-dashboard.php
@@ -1,6 +1,7 @@
 function download_plugin_bulk() {
+    check_ajax_referer('download_plugins_bulk_action', 'security');
     if (!current_user_can('manage_options')) {
         wp_die();
     }
@@ -10,6 +11,7 @@
 
 function download_theme_bulk() {
+    check_ajax_referer('download_themes_bulk_action', 'security');
     if (!current_user_can('manage_options')) {
         wp_die();
     }

Exploit Outline

1. Identify the administrative AJAX endpoints: The plugin registers 'download_plugin_bulk' and 'download_theme_bulk' as AJAX actions without verifying security nonces. 2. Craft a CSRF payload: Create a malicious HTML form or JavaScript snippet that targets '/wp-admin/admin-ajax.php' with the parameter 'action=download_plugin_bulk' or 'action=download_theme_bulk'. 3. Social Engineering: Trick a site administrator who is currently logged into the WordPress dashboard into visiting a malicious URL or clicking a link containing the payload. 4. Execution: The administrator's browser automatically sends the request including their session cookies. Since the server-side handler does not check for a nonce, it validates the request based on the administrator's session and executes the bulk archival logic. 5. Result: The site's plugins or themes are bundled into ZIP files and placed in the '/wp-content/uploads/' directory, which may lead to exposure of sensitive code or configuration data if the attacker can guess or discover the resulting filenames.

Check if your site is affected.

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