CVE-2025-13681

BFG Tools – Extension Zipper <= 1.0.7 - Authenticated (Administrator+) Path Traversal via 'first_file' Parameter

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

Description

The BFG Tools – Extension Zipper plugin for WordPress is vulnerable to Path Traversal in all versions up to, and including, 1.0.7. This is due to insufficient input validation on the user-supplied `first_file` parameter in the `zip()` function. This makes it possible for authenticated attackers, with Administrator-level access and above, to read the contents of arbitrary files and directories outside the intended `/wp-content/plugins/` directory, which can contain sensitive information such as wp-config.php.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.0.7
PublishedFebruary 13, 2026
Last updatedFebruary 14, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the technical steps required to exploit **CVE-2025-13681**, a Path Traversal vulnerability in the **BFG Tools – Extension Zipper** plugin. ### 1. Vulnerability Summary The BFG Tools – Extension Zipper plugin (version <= 1.0.7) contains an authenticated path traversal vul…

Show full research plan

This research plan outlines the technical steps required to exploit CVE-2025-13681, a Path Traversal vulnerability in the BFG Tools – Extension Zipper plugin.

1. Vulnerability Summary

The BFG Tools – Extension Zipper plugin (version <= 1.0.7) contains an authenticated path traversal vulnerability within its zip() function. The function accepts a user-supplied parameter first_file which is used to define the file or directory to be included in a ZIP archive. Because the plugin fails to properly sanitize this input (e.g., via realpath() validation or restricting the path to the intended directory), an Administrator can provide traversal sequences (like ../../) to include sensitive files from the server's root, such as wp-config.php, in the generated ZIP.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php (inferred, as zipping is typically an asynchronous admin task).
  • Action: Likely bfg_tools_extension_zipper_zip or similar (inferred from plugin slug).
  • Vulnerable Parameter: first_file.
  • Authentication: Required (Administrator+).
  • Preconditions: The plugin must be active. The attacker must have a valid session cookie for an Administrator user.

3. Code Flow (Inferred)

  1. Registration: The plugin registers an AJAX handler for zipping files, likely using add_action( 'wp_ajax_...', '...zip' ).
  2. Input Collection: The handler retrieves the first_file parameter from the $_POST or $_GET request.
  3. Path Construction: The code likely prepends a base path (e.g., WP_PLUGIN_DIR) to the first_file input.
  4. Vulnerable Sink: The constructed path is passed to a ZIP library (like ZipArchive) without checking if the resolved path remains within the intended directory.
  5. Output: The plugin generates a ZIP file and either provides a download link or direct output.

4. Nonce Acquisition Strategy

Since this is an administrative action, it is highly likely protected by a WordPress nonce.

  1. Identify Admin Page: Navigate to the plugin's settings/tools page. The slug is likely bfg-tools-extension-zipper.
  2. Locate Nonce: Use browser_eval to search for nonces in the global JavaScript scope or localized script objects.
    • Look for a variable like bfg_tools_vars or bfg_zip_nonce.
    • Search the HTML source for name="_wpnonce" or id="...nonce...".
  3. Extraction:
    // Example target if localized
    window.bfg_tools_settings?.nonce 
    // Or if in a form
    document.querySelector('input[name="_wpnonce"]')?.value
    

5. Exploitation Strategy

The goal is to zip and download wp-config.php.

Step 1: Authentication
Log in to the WordPress dashboard as an administrator.

Step 2: Nonce & Endpoint Discovery
Navigate to the BFG Tools interface (usually under "Tools" or its own menu). Identify the AJAX action by inspecting the "Zip" button's event listeners or the network tab during a legitimate zip operation.

Step 3: Crafting the Traversal Payload

  • Target File: wp-config.php (usually located 3 levels up from the plugins directory).
  • Payload: ../../../../wp-config.php.

Step 4: Execute HTTP Request
Using the http_request tool, send a POST request to admin-ajax.php:

{
  "method": "POST",
  "url": "http://localhost:8080/wp-admin/admin-ajax.php",
  "headers": {
    "Content-Type": "application/x-www-form-urlencoded"
  },
  "body": "action=bfg_tools_extension_zipper_zip&first_file=../../../../wp-config.php&_wpnonce=[NONCE_EXTRACTED_ABOVE]"
}

6. Test Data Setup

  1. Plugin Installation: Install and activate bfg-tools-extension-zipper version 1.0.7.
  2. Admin User: Ensure an admin user exists (e.g., admin/password).
  3. Environment Check: Ensure the standard wp-config.php exists in the WordPress root.

7. Expected Results

  • Success: The server responds with a 200 OK and either:
    • A link to a generated .zip file in the /wp-content/uploads/ directory.
    • A JSON response containing a success message and a file path.
  • Payload Verification: Downloading and extracting the generated ZIP will reveal the wp-config.php file containing database credentials (DB_PASSWORD, DB_USER).

8. Verification Steps

After the HTTP request, verify the existence of the leaked data:

  1. Check Uploads: Use ls -R /var/www/html/wp-content/uploads/ via terminal or WP-CLI to find the newly created ZIP file.
  2. Inspect ZIP Content:
    unzip -l /path/to/generated/file.zip
    
    Confirm that wp-config.php is listed in the archive.

9. Alternative Approaches

  • Directory Traversal: If first_file expects a directory, try zipping the entire root: ../../../../.
  • Direct File Access: If the plugin doesn't use ZIP but simply reads the file path to display info, the first_file parameter might be used in a file_get_contents sink, leading to direct disclosure in the response body.
  • Varying Path Depths: If ../../../../wp-config.php fails, try different depths (e.g., ../../../wp-config.php) depending on the exact plugin directory structure.
Research Findings
Static analysis — not yet PoC-verified

Summary

The BFG Tools – Extension Zipper plugin for WordPress is vulnerable to authenticated path traversal due to missing input validation on the 'first_file' parameter. Administrators can exploit this by using directory traversal sequences (e.g., ../) to include arbitrary sensitive files, such as wp-config.php, into a generated ZIP archive.

Vulnerable Code

// Inferred vulnerable function handling the zip request
// File: bfg-tools-extension-zipper/bfg-tools-extension-zipper.php (approximate)

public function zip() {
    if ( ! current_user_can( 'manage_options' ) ) {
        return;
    }

    $first_file = $_POST['first_file']; // Vulnerable: Direct use of user input without sanitization
    $plugin_dir = WP_PLUGIN_DIR;
    $source_path = $plugin_dir . '/' . $first_file;

    $zip = new ZipArchive();
    $zip_name = 'extension-' . time() . '.zip';
    $zip_file = wp_upload_dir()['path'] . '/' . $zip_name;

    if ($zip->open($zip_file, ZipArchive::CREATE) === TRUE) {
        if (is_dir($source_path)) {
            $this->add_directory_to_zip($zip, $source_path);
        } else {
            $zip->addFile($source_path, basename($source_path));
        }
        $zip->close();
    }
    // ... returns download link ...
}

Security Fix

--- a/bfg-tools-extension-zipper/bfg-tools-extension-zipper.php
+++ b/bfg-tools-extension-zipper/bfg-tools-extension-zipper.php
@@ -10,7 +10,14 @@
     if ( ! current_user_can( 'manage_options' ) ) {
         return;
     }
 
-    $first_file = $_POST['first_file'];
+    $first_file = sanitize_text_field($_POST['first_file']);
     $plugin_dir = WP_PLUGIN_DIR;
-    $source_path = $plugin_dir . '/' . $first_file;
+    $source_path = realpath($plugin_dir . '/' . $first_file);
+
+    // Ensure the resolved path starts with the intended plugin directory
+    if (strpos($source_path, realpath($plugin_dir)) !== 0) {
+        wp_send_json_error('Invalid path.');
+        return;
+    }
 
     $zip = new ZipArchive();

Exploit Outline

1. Authenticate as a WordPress Administrator. 2. Navigate to the BFG Tools – Extension Zipper interface to extract the required AJAX nonce and identify the correct action name (expected to be bfg_tools_extension_zipper_zip). 3. Craft a POST request to /wp-admin/admin-ajax.php with the 'first_file' parameter set to a traversal string targeting sensitive files, such as '../../../../wp-config.php'. 4. Submit the request including the valid nonce. 5. The plugin will create a ZIP archive containing the targeted sensitive file and provide a download link or location (typically in /wp-content/uploads/). 6. Download and extract the ZIP file to read the contents of wp-config.php.

Check if your site is affected.

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