CVE-2025-67931

BulletProof Security <= 6.9 - Unauthenticated Sensitive Information Exposure

mediumExposure of Sensitive Information to an Unauthorized Actor
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
7.0
Patched in
9d
Time to patch

Description

The BulletProof Security plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 6.9. This makes it possible for unauthenticated attackers to extract sensitive user or configuration data.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=6.9
PublishedJanuary 6, 2026
Last updatedJanuary 14, 2026
Affected pluginbulletproof-security

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan targets **CVE-2025-67931**, an unauthenticated sensitive information exposure vulnerability in the **BulletProof Security** plugin (versions <= 6.9). ### 1. Vulnerability Summary The BulletProof Security plugin facilitates security logging and system information reporting. In ver…

Show full research plan

This research plan targets CVE-2025-67931, an unauthenticated sensitive information exposure vulnerability in the BulletProof Security plugin (versions <= 6.9).

1. Vulnerability Summary

The BulletProof Security plugin facilitates security logging and system information reporting. In versions up to 6.9, certain endpoints—specifically those handled via the WordPress AJAX API or direct file access within the backup directory—fail to implement sufficient authentication or capability checks. This allows unauthenticated attackers to retrieve the Security Log (containing usernames, IP addresses, and request data) or the System Info Report (containing full server paths, PHP configuration, and database names).

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action (Inferred): bps_ajax_calls or bps_system_info
  • Parameter: bps_action=view_log or bps_action=system_info
  • Alternative Endpoint: Direct access to /wp-content/bps-backup/logs/bps_security_log.txt or /wp-content/bps-backup/master-backups/bps_php_error.log.
  • Authentication: None required (unauthenticated).
  • Preconditions: The plugin must be active. For log exposure, the "Security Log" feature must have recorded at least one event (e.g., a failed login).

3. Code Flow (Inferred)

  1. The plugin registers AJAX handlers in bulletproof-security.php or admin/includes/admin.php using add_action('wp_ajax_nopriv_bps_ajax_calls', 'bps_ajax_calls').
  2. The bps_ajax_calls function acts as a dispatcher, checking a sub-parameter like bps_action or bps_sub_action.
  3. For the view_log action, the code likely calls file_get_contents() on a path like WP_CONTENT_DIR . '/bps-backup/logs/bps_security_log.txt'.
  4. The function returns the file content via echo or wp_send_json() without checking current_user_can('manage_options').

4. Nonce Acquisition Strategy

BulletProof Security often uses nonces for its AJAX actions. Since this is an unauthenticated vulnerability, if a nonce is required, it must be exposed to logged-out users.

  1. Check for Nonce Exposure: BPS may localize nonces on the login page (wp-login.php) or the site frontend to support its security features.
  2. JS Variable Identification: Look for wp_localize_script calls using the handle bps-js or bps-admin-js.
  3. Extraction Steps:
    • Navigate to the homepage or the login page using browser_navigate.
    • Execute: browser_eval("window.bps_js_vars?.bps_nonce || window.bps_nonce").
    • Common localization keys (inferred): bps_js_vars, bps_ajax_nonce, or bps_nonce.

Note: If the handler is wp_ajax_nopriv_ and fails to call check_ajax_referer, no nonce is needed.

5. Exploitation Strategy

We will test two primary paths: the AJAX endpoint and direct file access.

Path A: AJAX Exposure (Primary)

  • Method: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=bps_ajax_calls&bps_action=view_log&nonce=[NONCE_IF_FOUND]
    
    Alternate Payload:
    action=bps_system_info
    

Path B: Direct File Access

  • Method: GET
  • URL 1: http://localhost:8080/wp-content/bps-backup/logs/bps_security_log.txt
  • URL 2: http://localhost:8080/wp-content/bps-backup/master-backups/bps_php_error.log

6. Test Data Setup

  1. Activate Plugin: Ensure BulletProof Security is active.
  2. Generate Logs:
    • Attempt to log in with a non-existent username: wp_cli or http_request to wp-login.php with log=attacker_user&pwd=password. This triggers an entry in the BPS Security Log.
  3. Enable Features: Use wp option update to ensure BPS logging is enabled if not on by default (BPS options are typically stored in bps_options).

7. Expected Results

  • For Security Log: The response should contain a text dump of security events, including timestamps, the string "BPS SECURITY LOG", and the username attacker_user.
  • For System Info: The response should contain a detailed report including ABSPATH, server environment variables, and WordPress version information.
  • HTTP Status: 200 OK for unauthenticated requests.

8. Verification Steps

  1. Check Logs via CLI:
    cat /var/www/html/wp-content/bps-backup/logs/bps_security_log.txt
    
  2. Compare Output: Confirm that the data returned by the http_request tool matches the content found in the file on disk.
  3. Verify Sensitive Data: Ensure the output contains sensitive strings like the database name (DB_NAME) or internal file paths.

9. Alternative Approaches

  • Directory Indexing: If index.php is missing in /wp-content/bps-backup/logs/, try a GET request to the directory itself to see if the server lists log files.
  • Sub-Action Fuzzing: If bps_action=view_log fails, try:
    • bps_action=system_info
    • bps_action=db_backup_log
    • bps_action=php_error_log
  • Referer Spoofing: Some BPS checks look for a specific Referer. Try setting Referer: http://localhost:8080/wp-admin/admin.php?page=bulletproof-security/admin/security-log/security-log.php.
Research Findings
Static analysis — not yet PoC-verified

Summary

The BulletProof Security plugin for WordPress (versions 6.9 and below) is vulnerable to unauthenticated sensitive information exposure. Attackers can access restricted log files and system configuration reports via the WordPress AJAX API or through direct file access to the plugin's backup directory, revealing usernames, server paths, and database details.

Vulnerable Code

// Inferred registration in admin/includes/admin.php or bulletproof-security.php
add_action('wp_ajax_nopriv_bps_ajax_calls', 'bps_ajax_calls');

// Inferred handler function
function bps_ajax_calls() {
    $bps_action = $_POST['bps_action'];
    if ($bps_action == 'view_log') {
        // Vulnerable: Lacks current_user_can() or check_ajax_referer() protection
        $log_path = WP_CONTENT_DIR . '/bps-backup/logs/bps_security_log.txt';
        if (file_exists($log_path)) {
            echo file_get_contents($log_path);
            exit;
        }
    }
}

---

// Directory: /wp-content/bps-backup/logs/
// Log file: bps_security_log.txt
// Log file: bps_php_error.log
// Accessible directly via HTTP GET requests if directory permissions are misconfigured or .htaccess is missing.

Security Fix

--- admin/includes/admin.php
+++ admin/includes/admin.php
@@ -10,1 +10,0 @@
-add_action('wp_ajax_nopriv_bps_ajax_calls', 'bps_ajax_calls');
 
 function bps_ajax_calls() {
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_die( __( 'Access Denied' ) );
+    }
+    check_ajax_referer( 'bps_ajax_nonce', 'nonce' );

--- /wp-content/bps-backup/logs/.htaccess
+++ /wp-content/bps-backup/logs/.htaccess
+Order Deny,Allow
+Deny from all

Exploit Outline

An unauthenticated attacker can exploit this vulnerability through two primary methods: 1. AJAX Request: Sending a POST request to `/wp-admin/admin-ajax.php` with the parameters `action=bps_ajax_calls` and `bps_action=view_log`. If the plugin requires a nonce but exposes it to unauthenticated users via `wp_localize_script`, the attacker extracts the nonce from the page source and includes it in the request. 2. Direct File Access: Accessing known sensitive file paths directly through the browser, such as `http://localhost/wp-content/bps-backup/logs/bps_security_log.txt` or `http://localhost/wp-content/bps-backup/master-backups/bps_php_error.log`. Successful exploitation returns the contents of the Security Log (including usernames and IP addresses) or System Info reports (including full server paths, PHP configuration, and database names).

Check if your site is affected.

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