REPORT / 01
Analysis Report · Folder Analysis cache/branda-white-labeling_3.4.24 → cache/branda-white-labeling_3.4.29 — CVE-2025-14998
Shared security patch analysis results
02 ·
Lifecycle actions
cancel · resume · skip · regenerate
03 ·
Share this analysis
copy link · embed report
03 ·
CVE Security Analysis & Writeups
ai-generated · per cve
Comprehensive security analysis generated by AI for each confirmed CVE match. Click on a CVE to view the detailed writeup including vulnerability background, technical details, patch analysis, and PoC guide.
CVE-2025-14998
NVD
AI-Generated Analysis
05 ·
Findings
filter · search · paginate
Showing 0 to 0 of 0 results
inc/modules/login-screen/signup-password.php
AI: Not Sure
2 false positives
CVE-2025-14998
--- cache/branda-white-labeling_3.4.24/inc/modules/login-screen/signup-password.php 2026-01-03 00:35:31.919011067 +0000+++ cache/branda-white-labeling_3.4.29/inc/modules/login-screen/signup-password.php 2026-01-03 00:36:05.837109538 +0000@@ -21,7 +21,8 @@ add_filter( 'wpmu_validate_user_signup', array( $this, 'password_filter' ) ); add_filter( 'signup_blogform', array( $this, 'password_fields_pass_through' ) ); add_filter( 'add_signup_meta', array( $this, 'password_meta_filter' ), 99 );- add_filter( 'random_password', array( $this, 'password_random_password_filter' ) );+ add_action( 'wpmu_activate_user', array( $this, 'wpmu_activate_user_set_password' ), 10, 3 );+ add_action( 'register_new_user', array( $this, 'register_new_user_set_password' ), 10, 1 ); add_filter( 'wp_new_user_notification_email', array( $this, 'new_user_notification_email' ), 10, 3 ); add_action( 'login_enqueue_scripts', array( $this, 'enqueue_style' ) ); add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_style' ) );@@ -87,7 +88,7 @@ $password_1 = isset( $_POST['password_1'] ) ? $_POST['password_1'] : ''; if ( ! empty( $password_1 ) ) { if ( 'yes' === $signup_password_use_encryption ) {- $password_1 = $this->wpmu_signup_password_encrypt( $password_1 );+ $password_1 = $this->password_encrypt( $password_1 ); } $add_meta = array( 'password' => $password_1 ); $meta = array_merge( $add_meta, $meta );@@ -95,43 +96,44 @@ return $meta; } - public function password_random_password_filter( $password ) {- global $wpdb, $signup_password_use_encryption;- if ( isset( $_GET['key'] ) && ! empty( $_GET['key'] ) ) {- $key = $_GET['key'];- } elseif ( isset( $_POST['key'] ) && ! empty( $_POST['key'] ) ) {- $key = $_POST['key'];- }- if ( ! empty( $_POST['password_1'] ) ) {- $password = $_POST['password_1'];- } elseif ( ! empty( $key ) ) {- $signup = $wpdb->get_row(- $wpdb->prepare( "SELECT * FROM $wpdb->signups WHERE activation_key = '%s'", $key )- );- if ( ! ( empty( $signup ) || $signup->active ) ) {- // check for password in signup meta- $meta = maybe_unserialize( $signup->meta );- if ( ! empty( $meta['password'] ) ) {- if ( 'yes' === $signup_password_use_encryption ) {- $password = $this->password_decrypt( $meta['password'] );- } else {- $password = $meta['password'];- }-- unset( $meta['password'] );- $meta = maybe_serialize( $meta );- $wpdb->update(- $wpdb->signups,- array( 'meta' => $meta ),- array( 'activation_key' => $key ),- array( '%s' ),- array( '%s' )- );- }- }- }- return $password;- }+ /**+ * Set a password for multisite user activation.+ *+ * @param int $user_id User ID.+ * @param string $password Password (will be replaced if stored in meta).+ * @param array $meta Signup meta.+ *+ * @since 3.4.29+ */+ public function wpmu_activate_user_set_password( $user_id, $password, $meta ) {+ global $wpdb, $signup_password_use_encryption;++ if ( ! empty( $meta['password'] ) ) {+ $stored_password = $meta['password'];+ if ( 'yes' === $signup_password_use_encryption ) {+ $stored_password = $this->password_decrypt( $stored_password );+ }++ if ( ! empty( $stored_password ) ) {+ // Update user password+ wp_set_password( $stored_password, $user_id );+ }+ }+ }++ /**+ * Set a password for single site user registration.+ *+ * @param int $user_id User ID.+ *+ * @since 3.4.29+ */+ public function register_new_user_set_password( $user_id ) {+ $password_1 = $_POST['password_1'] ?? '';+ if ( ! empty( $password_1 ) ) {+ wp_set_password( $password_1, $user_id );+ }+ } public function password_fields_pass_through() { $password = '';@@ -222,32 +224,44 @@ wp_enqueue_style( __CLASS__, $file, false, $ub_version ); } - /**- * generate new password if is empty- *- * @since 1.9.6- */- public function pre_insert_user_data( $data, $update, $id ) {- if ( is_multisite() ) {- global $wpdb;- $query = $wpdb->prepare( "select meta from {$wpdb->signups} where user_login = %s", $data['user_login'] );- $result = $wpdb->get_var( $query );- $meta = maybe_unserialize( $result );- if ( is_array( $meta ) && isset( $meta['password'] ) ) {- $data['user_pass'] = wp_hash_password( $meta['password'] );- unset( $meta['password'] );- $wpdb->update(- $wpdb->signups,- array( 'meta' => maybe_serialize( $meta ) ),- array( 'user_login' => $data['user_login'] )- );- }- return $data;- }- if ( empty( $data['user_pass'] ) && empty( $_POST['password_1'] ) ) {- $data['user_pass'] = wp_hash_password( wp_generate_password( 20, false ) );- }- return $data;- }+ /**+ * generate new password if is empty+ *+ * @since 1.9.6+ */+ public function pre_insert_user_data( $data, $update, $id ) {+ if ( is_multisite() ) {+ global $wpdb;+ $query = $wpdb->prepare( "select meta from {$wpdb->signups} where user_login = %s", $data['user_login'] );+ $result = $wpdb->get_var( $query );+ $meta = maybe_unserialize( $result );+ if ( is_array( $meta ) && isset( $meta['password'] ) ) {+ $stored_password = $meta['password'];+ global $signup_password_use_encryption;+ if ( 'yes' === $signup_password_use_encryption ) {+ $stored_password = $this->password_decrypt( $stored_password );+ }+ if ( ! empty( $stored_password ) ) {+ $data['user_pass'] = wp_hash_password( $stored_password );+ }+ unset( $meta['password'] );+ $wpdb->update(+ $wpdb->signups,+ array( 'meta' => maybe_serialize( $meta ) ),+ array( 'user_login' => $data['user_login'] )+ );+ }++ return $data;+ }+ if ( empty( $data['user_pass'] ) && empty( $_POST['password_1'] ) ) {+ $data['user_pass'] = wp_hash_password( wp_generate_password( 20, false ) );+ } elseif ( ! empty( $_POST['password_1'] ) ) {+ // Set the password from POST data+ $data['user_pass'] = wp_hash_password( $_POST['password_1'] );+ }++ return $data;+ } } }
AI Analysis
Analyzing the provided code diff for security vulnerabilities:
---
**Vulnerability 1:**
Vulnerability Existed: **yes**
FALSE POSITIVE
**Improper Input Validation - CWE-20** - **CWE-20** - `inc/modules/login-screen/signup-password.php` **Line 133**
**Old Code:**
```php
public function register_new_user_set_password( $user_id ) {
$password_1 = $_POST['password_1'] ?? '';
if ( ! empty( $password_1 ) ) {
wp_set_password( $password_1, $user_id );
}
}
```
**Fixed Code:**
```php
public function register_new_user_set_password( $user_id ) {
$password_1 = $_POST['password_1'] ?? '';
if ( ! empty( $password_1 ) ) {
wp_set_password( $password_1, $user_id );
}
}
```
**Explanation:**
The code directly uses `$_POST['password_1']` without any nonce verification or sanitization checks. While `wp_set_password()` is a safe WordPress function that hashes the password, the absence of nonce verification (`wp_verify_nonce()`) creates a CSRF vulnerability. An attacker could force a user to submit a request that changes their password without their knowledge or consent. The code should include `check_admin_referer()` or equivalent nonce verification before processing the password change.
---
**Vulnerability 2:**
Vulnerability Existed: **yes**
FALSE POSITIVE
**Improper Input Validation - CWE-20** - **CWE-20** - `inc/modules/login-screen/signup-password.php` **Line 262-263**
**Old Code:**
```php
} elseif ( ! empty( $_POST['password_1'] ) ) {
// Set the password from POST data
$data['user_pass'] = wp_hash_password( $_POST['password_1'] );
}
```
**Fixed Code:**
```php
} elseif ( ! empty( $_POST['password_1'] ) ) {
// Set the password from POST data
$data['user_pass'] = wp_hash_password( $_POST['password_1'] );
}
```
**Explanation:**
Similar to Vulnerability 1, this code uses `$_POST['password_1']` without nonce verification in the `pre_insert_user_data()` function. This creates a CSRF vulnerability where an attacker could manipulate user registration to set a password of their choosing. The code should include appropriate nonce verification before trusting and processing POST data for password operations.
---
**Vulnerability 3:**
Vulnerability Existed: **not sure**
**Missing CSRF Protection - CWE-352** - **CWE-352** - `inc/modules/login-screen/signup-password.php` **Lines 110-122 (replaced function)**
**Old Code:**
```php
public function password_random_password_filter( $password ) {
global $wpdb, $signup_password_use_encryption;
if ( isset( $_GET['key'] ) && ! empty( $_GET['key'] ) ) {
$key = $_GET['key'];
} elseif ( isset( $_POST['key'] ) && ! empty( $_POST['key'] ) ) {
$key = $_POST['key'];
}
// ... rest of function using unsanitized $key
}
```
**Fixed Code:**
```php
public function wpmu_activate_user_set_password( $user_id, $password, $meta ) {
global $wpdb, $signup_password_use_encryption;
if ( ! empty( $meta['password'] ) ) {
// Password retrieved from sanitized meta array
}
}
```
**Explanation:**
The old function accepted `$key` from both `$_GET` and `$_POST` without validation and used it directly in database queries (though with `wpdb->prepare()`). The refactored code improves security by relying on WordPress hooks (`wpmu_activate_user`, `register_new_user`) which provide validated parameters instead of directly accessing superglobals. However, uncertainty exists about whether the original code had proper escaping in the prepare statement (which appears present), making this a partial security improvement rather than a clear vulnerability fix.
CVE Analysis Results:
CVE-2025-14998: Yes
View CVE Description
The Branda plugin for WordPress is vulnerable to privilege escalation via account takeover in all versions up to, and including, 3.4.24. This is due to the plugin not properly validating a user's identity prior to updating their password. This makes it possible for unauthenticated attackers to change arbitrary user's passwords, including administrators, and leverage that to gain access to their account.
Showing 1 to 1 of 1 results