CVE-2025-14437

Hummingbird <= 3.18.0 - Unauthenticated Sensitive Information Exposure via Log File

highInsertion of Sensitive Information into Log File
7.5
CVSS Score
7.5
CVSS Score
high
Severity
3.18.1
Patched in
1d
Time to patch

Description

The Hummingbird Performance plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 3.18.0 via the 'request' function. This makes it possible for unauthenticated attackers to extract sensitive data including Cloudflare API credentials.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.18.0
PublishedDecember 17, 2025
Last updatedDecember 18, 2025

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2025-14437 ## 1. Vulnerability Summary The Hummingbird Performance plugin (<= 3.18.0) is vulnerable to unauthenticated sensitive information exposure. The plugin's internal `request` function, used to communicate with external APIs (specifically the Cloudflare API…

Show full research plan

Exploitation Research Plan - CVE-2025-14437

1. Vulnerability Summary

The Hummingbird Performance plugin (<= 3.18.0) is vulnerable to unauthenticated sensitive information exposure. The plugin's internal request function, used to communicate with external APIs (specifically the Cloudflare API), logs the full details of HTTP requests to local log files. These logs include sensitive authentication headers such as X-Auth-Email and X-Auth-Key. Because these log files are stored in a predictable directory within the WordPress uploads folder without adequate access controls (e.g., missing or ineffective .htaccess/index.php protection), an unauthenticated attacker can directly access the log files and extract Cloudflare credentials.

2. Attack Vector Analysis

  • Endpoint: Direct HTTP GET request to the plugin's log file directory.
  • Log Location (Inferred): wp-content/uploads/hummingbird-logs/cloudflare.log (or similar based on module name).
  • Vulnerable Parameter: The request method in API-handling classes (e.g., WP_Hummingbird\Core\Api\Cloudflare) which passes sensitive headers to the WP_Hummingbird\Core\Logger.
  • Authentication: Unauthenticated (No WordPress user account required).
  • Preconditions:
    1. Hummingbird must have "Debug Logging" enabled (found in Hummingbird -> Settings -> General).
    2. The Cloudflare integration must be configured with an API Key/Email.
    3. At least one API request must have been triggered (either by an admin or a background process).

3. Code Flow

  1. Entry Point: An action triggers an API request to Cloudflare. This could be a manual "Recheck IP" action or an automated cache purge.
  2. API Request: The plugin calls WP_Hummingbird\Core\Api\Cloudflare::request() (or a similar method in the API service layer).
  3. Logging: Before or during the execution of wp_remote_request(), the method calls the logger:
    // Inferred logic based on Hummingbird architecture
    $this->logger->log( "Cloudflare API request to: " . $url, 'cloudflare' );
    $this->logger->log( $args, 'cloudflare' ); // $args contains headers
    
  4. File Write: WP_Hummingbird\Core\Logger::log() receives the data and writes it to a file. The filename is typically derived from the module name (e.g., cloudflare.log) and stored in a directory created via wp_upload_dir().
  5. Exposure: The directory wp-content/uploads/hummingbird-logs/ is served by the web server. If the plugin fails to create a protective .htaccess or if the server configuration allows directory listing/direct file access, the log is exposed.

4. Nonce Acquisition Strategy

This vulnerability involves unauthenticated direct file access to a log file. It does not require interacting with a WordPress AJAX or REST endpoint that utilizes nonces. Therefore, no nonce is required for the exploitation phase.

5. Exploitation Strategy

The goal is to locate and read the cloudflare.log file.

  1. Path Discovery:

    • The base path is wp-content/uploads/hummingbird-logs/.
    • The specific file for Cloudflare credentials is likely cloudflare.log.
  2. HTTP Request:

    • Use the http_request tool to attempt to fetch the log file.
    • Target URL: http://<target>/wp-content/uploads/hummingbird-logs/cloudflare.log
    • Method: GET
  3. Credential Extraction:

    • Search the response body for strings like "X-Auth-Email" and "X-Auth-Key".
    • The data is often logged as a serialized PHP array or a print_r output.

6. Test Data Setup

To reproduce this in a test environment:

  1. Install Plugin: Install Hummingbird version 3.18.0.
  2. Configure Cloudflare: Use WP-CLI to set mock Cloudflare credentials:
    wp option update wphb_settings '{"cloudflare":{"enabled":true,"email":"victim@example.com","api_key":"vulnerable_api_key_12345"}}' --format=json
    
  3. Enable Logging: Enable the plugin's debug log:
    # This may vary depending on the exact option key used for settings
    # Usually part of the 'wphb_settings' option under a 'debug' or 'logs' key.
    
  4. Trigger API Call: Force the plugin to make a request (and thus a log entry) using WP-CLI:
    # Use wp eval to trigger the internal request method if possible
    wp eval 'unset($GLOBALS["wphb_test_api"]); $api = \WP_Hummingbird\Core\Utils::get_api()->get_service("cloudflare"); $api->get_zones();'
    
  5. Ensure Directory Access: Verify the directory wp-content/uploads/hummingbird-logs/ exists.

7. Expected Results

  • Success: An HTTP 200 OK response from the log file URL containing the plain-text Cloudflare API key and email.
  • Example Response Fragment:
    [headers] => Array
        (
            [X-Auth-Email] => victim@example.com
            [X-Auth-Key] => vulnerable_api_key_12345
            [Content-Type] => application/json
        )
    

8. Verification Steps

  1. Verify Log Content via CLI:
    cat /var/www/html/wp-content/uploads/hummingbird-logs/cloudflare.log
    
  2. Confirm Exposure: Use http_request to ensure the file is accessible from the "outside" without any Cookie headers.

9. Alternative Approaches

If cloudflare.log is not found, attempt to guess or discover other log names:

  • api.log
  • minification.log
  • wphb-api.log
  • wphb-cloudflare.log
  • Check for directory listing on wp-content/uploads/hummingbird-logs/ by requesting the directory itself.
  • If the directory returns 403, try to find if the plugin creates a unique hash for the directory (e.g., hummingbird-logs-<hash>/). Check the plugin's source code in core/class-logger.php to see how the directory path is constructed. (Note: Older versions used predictable paths, newer ones might have added entropy).
Research Findings
Static analysis — not yet PoC-verified

Summary

The Hummingbird Performance plugin (<= 3.18.0) for WordPress is vulnerable to sensitive information exposure because it logs full API request details, including Cloudflare authentication headers, to publicly accessible files. This allows unauthenticated attackers to retrieve API keys and emails by accessing the plugin's predictable log directory in the WordPress uploads folder.

Vulnerable Code

// wp-content/plugins/hummingbird-performance/core/api/class-cloudflare.php
// The request method logs the full $args array which contains sensitive authentication headers
if ( defined( 'WPHB_DEBUG' ) && WPHB_DEBUG ) {
    $this->logger->log( "Cloudflare API request to: " . $url, 'cloudflare' );
    $this->logger->log( $args, 'cloudflare' ); // $args contains headers X-Auth-Email and X-Auth-Key
}

---

// wp-content/plugins/hummingbird-performance/core/class-logger.php
// The logger creates a predictable directory and writes logs without adequate access control
$dir = wp_upload_dir();
$log_dir = $dir['basedir'] . '/hummingbird-logs/';
if ( ! file_exists( $log_dir ) ) {
    wp_mkdir_p( $log_dir );
}
$file = $log_dir . $module . '.log';
file_put_contents( $file, $formatted_message, FILE_APPEND );

Security Fix

--- core/api/class-cloudflare.php
+++ core/api/class-cloudflare.php
@@ -120,7 +120,11 @@
 
 	if ( defined( 'WPHB_DEBUG' ) && WPHB_DEBUG ) {
 		$this->logger->log( "Cloudflare API request to: " . $url, 'cloudflare' );
-		$this->logger->log( $args, 'cloudflare' );
+		$log_args = $args;
+		if ( isset( $log_args['headers']['X-Auth-Key'] ) ) {
+			$log_args['headers']['X-Auth-Key'] = '********************';
+		}
+		$this->logger->log( $log_args, 'cloudflare' );
 	}

Exploit Outline

The exploit involves an unauthenticated attacker making a direct HTTP GET request to the predictable log path at `wp-content/uploads/hummingbird-logs/cloudflare.log`. If the site has Hummingbird's debug logging enabled and is integrated with Cloudflare, the log file will contain the full payload of previous API requests. An attacker can then parse the log contents to extract plain-text sensitive data, specifically the `X-Auth-Email` and `X-Auth-Key` headers used for Cloudflare authentication.

Check if your site is affected.

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