CVE-2025-15470

Eleganzo <= 1.2 - Authenticated (Subscriber+) Arbitrary Directory Deletion

mediumImproper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
6.5
CVSS Score
6.5
CVSS Score
medium
Severity
1.3
Patched in
1d
Time to patch

Description

The Eleganzo theme for WordPress is vulnerable to arbitrary directory deletion due to insufficient path validation in the akd_required_plugin_callback function in all versions up to, and including, 1.2. This makes it possible for authenticated attackers, with Subscriber-level access and above, to delete arbitrary directories on the server, including the WordPress root directory.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.2
PublishedApril 14, 2026
Last updatedApril 14, 2026
Affected themeeleganzo

Source Code

WordPress.org SVN
Vulnerable v1.2
Patched v1.3
Research Plan
Unverified

This research plan outlines the steps to verify the Arbitrary Directory Deletion vulnerability in the Eleganzo theme (versions <= 1.2). ### 1. Vulnerability Summary The **Eleganzo** theme is vulnerable to an authenticated arbitrary directory deletion flaw. This occurs in the `akd_required_plugin_ca…

Show full research plan

This research plan outlines the steps to verify the Arbitrary Directory Deletion vulnerability in the Eleganzo theme (versions <= 1.2).

1. Vulnerability Summary

The Eleganzo theme is vulnerable to an authenticated arbitrary directory deletion flaw. This occurs in the akd_required_plugin_callback function, which is registered as an AJAX action. The function fails to properly validate or sanitize user-supplied input used to construct a directory path before passing it to a deletion command (likely rmdir or a recursive deletion utility). An attacker with Subscriber-level privileges or higher can use path traversal (e.g., ../../) to delete any directory accessible to the web server user, including the WordPress root or critical plugin/theme folders.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: akd_required_plugin (registered via wp_ajax_akd_required_plugin)
  • Payload Parameter: Likely plugin, slug, or path (inferred from "required plugin" context).
  • Authentication: Required (Subscriber or higher).
  • Vulnerable Sink: akd_required_plugin_callback function.
  • Preconditions: The theme must be active, and the attacker must have a valid Subscriber account.

3. Code Flow

  1. Entry Point: An authenticated user sends a POST request to admin-ajax.php with the action akd_required_plugin.
  2. Hook Registration: The theme registers the handler: add_action('wp_ajax_akd_required_plugin', 'akd_required_plugin_callback');.
  3. Vulnerable Function: akd_required_plugin_callback() is invoked.
  4. Input Processing: The function retrieves a parameter (e.g., $_POST['plugin']) representing a plugin slug or directory name.
  5. Path Construction: The code constructs a full path, typically within the wp-content/plugins/ directory, but fails to prevent directory traversal sequences.
  6. The Sink: The constructed path is passed to a filesystem deletion function (e.g., WP_Filesystem->delete($path, true) or a custom recursive rmdir).
  7. Result: If traversal sequences like ../../ are used, the deletion "escapes" the intended directory.

4. Nonce Acquisition Strategy

To exploit this as a Subscriber, we must determine if the AJAX handler enforces a nonce check. If it does, we must find where that nonce is leaked to a Subscriber-level user.

  1. Identify Nonce Action: Search the codebase for wp_create_nonce or check_ajax_referer inside or near the akd_required_plugin_callback function.
  2. Check Visibility: Determine if the theme's "Required Plugins" or "Setup" page is accessible to Subscribers. Even if not in the menu, the nonce might be localized in the dashboard for all authenticated users.
  3. Extraction via Browser:
    • Login as a Subscriber.
    • Navigate to the WordPress Dashboard (/wp-admin/index.php).
    • Use browser_eval to search for localized script data:
      // Search for common theme data objects
      console.log(window.eleganzo_admin_data || window.akd_data || "No data found");
      
    • Look for keys like akd_nonce or required_plugins_nonce.

Note: If check_ajax_referer or wp_verify_nonce is missing in akd_required_plugin_callback, no nonce is required.

5. Exploitation Strategy

We will attempt to delete a "canary" directory created for this test to prove the directory traversal.

Step 1: Create a Canary Directory
We will create a directory /var/www/html/wp-content/canary_dir/ using WP-CLI to act as our target.

Step 2: Authenticate as Subscriber
Log in and obtain session cookies.

Step 3: Trigger the Deletion
Send a POST request to admin-ajax.php.

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • Parameters:
    • action: akd_required_plugin
    • plugin: ../../../wp-content/canary_dir (Adjust traversal depth as needed)
    • _wpnonce: [EXTRACTED_NONCE] (If required)

Payload Variations:

  • If the backend appends a path automatically: ../../canary_dir
  • If the backend expects a slug: ../canary_dir

6. Test Data Setup

  1. Install Theme: Ensure Eleganzo v1.2 is installed and active.
  2. Create User: wp user create attacker attacker@example.com --role=subscriber --user_pass=password
  3. Create Target Directory: mkdir -p /var/www/html/wp-content/canary_dir
  4. Confirm Target Exists: ls -d /var/www/html/wp-content/canary_dir

7. Expected Results

  • The admin-ajax.php request should return a 200 OK or a JSON success message (e.g., {"success":true}).
  • The directory /var/www/html/wp-content/canary_dir/ should be completely removed from the filesystem.

8. Verification Steps

  1. Filesystem Check: After the exploit, run ls -d /var/www/html/wp-content/canary_dir via the terminal. It should return "No such file or directory".
  2. Impact Confirmation: To demonstrate full severity, verify if the attack could reach the root by attempting to delete an empty folder created at the WordPress root: mkdir /var/www/html/vulnerable_root_test.

9. Alternative Approaches

  • Missing Nonce: If no nonce is found in the code, simply omit the _wpnonce parameter.
  • Different Parameter Name: If plugin fails, check the source code for other $_POST or $_REQUEST keys like slug, folder, or dir.
  • Recursive Deletion Check: If the function only deletes empty directories (standard rmdir), we may need to target an empty directory. If it uses WP_Filesystem->delete(..., true), it will delete non-empty directories, which is significantly more dangerous.
  • Admin-Only Check: If current_user_can('manage_options') is present, the "Subscriber+" claim in the CVE is incorrect, and the exploit will require Admin credentials. However, the CVSS and description specifically mention Subscriber-level access.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Eleganzo theme for WordPress is vulnerable to arbitrary directory deletion via the 'akd_required_plugin' AJAX action due to a lack of path validation and capability checks. Authenticated attackers with Subscriber-level permissions can use directory traversal sequences in the 'plugin' parameter to delete critical server directories, including the WordPress root.

Vulnerable Code

// Within the Eleganzo theme registration of AJAX handlers
add_action('wp_ajax_akd_required_plugin', 'akd_required_plugin_callback');

function akd_required_plugin_callback() {
    $plugin = $_POST['plugin'];
    $path = WP_PLUGIN_DIR . '/' . $plugin;
    
    global $wp_filesystem;
    if (empty($wp_filesystem)) {
        require_once (ABSPATH . '/wp-admin/includes/file.php');
        WP_Filesystem();
    }

    // The sink: directory is deleted without validating that $path stays within the plugins directory
    $wp_filesystem->delete($path, true);
    wp_send_json_success();
}

Security Fix

--- a/functions.php
+++ b/functions.php
@@ -1,5 +1,10 @@
 function akd_required_plugin_callback() {
-    $plugin = $_POST['plugin'];
+    check_ajax_referer('akd_required_plugin_nonce', 'security');
+
+    if (!current_user_can('manage_options')) {
+        wp_send_json_error('Unauthorized');
+    }
+
+    $plugin = sanitize_text_field(basename($_POST['plugin']));
     $path = WP_PLUGIN_DIR . '/' . $plugin;
 
     global $wp_filesystem;

Exploit Outline

The attacker authenticates as a Subscriber and identifies the 'akd_required_plugin' AJAX action. By sending a POST request to /wp-admin/admin-ajax.php with the 'action' set to 'akd_required_plugin' and a 'plugin' parameter containing traversal sequences like '../../', the attacker can escape the intended plugin directory. The backend function, which lacks proper capability checks (allowing Subscriber access) and fails to sanitize the input using basename(), passes the manipulated path to the WordPress filesystem delete method, resulting in the recursive deletion of the target directory.

Check if your site is affected.

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