BulletProof Security <= 6.9 - Unauthenticated Sensitive Information Exposure
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:NTechnical Details
<=6.9Source Code
WordPress.org SVNThis 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_callsorbps_system_info - Parameter:
bps_action=view_logorbps_action=system_info - Alternative Endpoint: Direct access to
/wp-content/bps-backup/logs/bps_security_log.txtor/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)
- The plugin registers AJAX handlers in
bulletproof-security.phporadmin/includes/admin.phpusingadd_action('wp_ajax_nopriv_bps_ajax_calls', 'bps_ajax_calls'). - The
bps_ajax_callsfunction acts as a dispatcher, checking a sub-parameter likebps_actionorbps_sub_action. - For the
view_logaction, the code likely callsfile_get_contents()on a path likeWP_CONTENT_DIR . '/bps-backup/logs/bps_security_log.txt'. - The function returns the file content via
echoorwp_send_json()without checkingcurrent_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.
- Check for Nonce Exposure: BPS may localize nonces on the login page (
wp-login.php) or the site frontend to support its security features. - JS Variable Identification: Look for
wp_localize_scriptcalls using the handlebps-jsorbps-admin-js. - 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, orbps_nonce.
- Navigate to the homepage or the login page using
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:
Alternate Payload:action=bps_ajax_calls&bps_action=view_log&nonce=[NONCE_IF_FOUND]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
- Activate Plugin: Ensure BulletProof Security is active.
- Generate Logs:
- Attempt to log in with a non-existent username:
wp_cliorhttp_requesttowp-login.phpwithlog=attacker_user&pwd=password. This triggers an entry in the BPS Security Log.
- Attempt to log in with a non-existent username:
- Enable Features: Use
wp option updateto ensure BPS logging is enabled if not on by default (BPS options are typically stored inbps_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 OKfor unauthenticated requests.
8. Verification Steps
- Check Logs via CLI:
cat /var/www/html/wp-content/bps-backup/logs/bps_security_log.txt - Compare Output: Confirm that the data returned by the
http_requesttool matches the content found in the file on disk. - 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.phpis 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_logfails, try:bps_action=system_infobps_action=db_backup_logbps_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.
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
@@ -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' ); +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.