
Эксплойт доказательства концепции для CVE-2026-11551, уязвимости неаутентифицированного повышения привилегий в плагине Branda White Label для WordPress, позволяющей захватить учетную запись через двойное хеширование пароля.
White Label & Branding, Free Login Page Customizer <= 3.4.29 — Неаутентифицированное повышение привилегий через захват учётной записи
wp_update_user( $userdata )
│
├── wp_hash_password( $userdata['user_pass'] ) ← Строка 2709: УЖЕ ЗАХЭШИРОВАН
│
└── wp_insert_user( $userdata )
│
├── $user_pass = $userdata['user_pass'] ← Строка 2228: ЗАХЭШИРОВАН
│
├── $data = compact('user_pass', ...) ← Строка 2469: ЗАХЭШИРОВАН
│
├── apply_filters('wp_pre_inserter_id)
│ │
│ └── Branda: pre_insert_u
│ │
│ ├── запрос wp_sig['user_login']
│ ├── если meta['pas
│ │ $data['user_ta['password'])
│ │ ↑
│ ┌───
│ │
│ ↓
│ ДВОЙНОЙ ХЭШ: wp_d($raw))
│
└── $wpdb->update( $wpdb->users, $data, ... ) ← Строка 2515: ДВОЙНОЙ ХЭШ СОХРАНЁН
/**
* BRANDA - signup-password.php
* Фильтр: wp_pre_insert_user_data
*/
public function pre_insert_user_data( $data,
// ❌ НЕТ ПРОВЕРКИ: if ($update) return
// ❌ Этот фильтр ВЫПОЛНЯЕТСЯ для INSERT И
if ( is_multisite() ) {
global $wpdb;
// ❌ $data['user_login'] из POST и редактирования пользователя
$query = $wpdb->prepare(
"SELECT meta FROM {$wpdb->signup
$data['user_login'] // ← может быть изменён атакующим
);
$result = $wpdb->get_var( $query );
$meta = maybe_unserialize( $result
if ( is_array( $meta ) && isset( $me
// ❌ ДВОЙНОЙ ХЭШ: WordPress УЖЕ захэшировал до выполнения этого фильтра
// $meta['password'] = "mysecret
// wp_hash_password("mysecretpasama от WP core)
// wp_hash_password("$P$Bxyz..."от Branda)
$data['user_pass'] = wp_hash_pas
unset( $meta['password'] );
$wpdb->update(
$wpdb->signups,
array( 'meta' => maybe_seria
array( 'user_login' => $data
);
}
return $data;
}
// ...
}
// wp-includes/user.php:2706
if ( ! empty( $userdata['user_pass'] ) && $u_user_data->user_pass ) {
$plaintext_pass = $userdata['user
$userdata['user_pass'] = wp_hash_passwor // ← ХЭШ #1
}
// wp-includes/user.php:2228 (путь обновления)
$user_pass = ! empty( $userdata['user_pass'] $old_user_data->user_pass;
// $user_pass теперь = "$P$Bxyz...УЖЕ ЗАХЭШИРОВАН"
// wp-includes/user.php:2505
$data = apply_filters( 'wp_pre_insert_user_dd, $userdata );
// Фильтр Branda выполняется, $data['user_pass'] УЖЕ ЗАХЭШИРОВАН из строки 2228
┌─────────────┬──────────────────────────┐
│ user_login │ meta (serialized) │
├─────────────┼──────────────────────────│
│ victim_user │ a:1:{s:8:"password";s:10:"H4cker123!"}│
└─────────────┴──────────────────────────┴
┌────────────────────────────────────────────┐
│ Поле: имя пользователя │
│ Значение: victim_user ← ИЗМЕНЕНО │
└────────────────────────────────────────────┴
wp_update_user({ID: 2, user_login: "victim_user", ...})
│
├── user_pass = wp_hash_password(old_password) ← ХЭШ #1
│
└── wp_insert_user({ID: 2, user_login: "victim_user", user_pass: "$P$Bhash1"})
│
└── apply_filters('wp_pre_insert_user_data', $data, true, 2)
│
└── Branda: pre_insert_user_data()
│
├── $data['user_login'] = "victim_user"
│
├── SELECT meta FROM wp_signups WHERE user_login = "victim_user"
│ → meta = 'a:1:{s:8:"password";s:10:"H4cker123!"}'
│
├── $meta['password'] = "H4cker123!"
│
└── $datword("H4cker123!")
← ХЭШ #2 (ДВОЙНОЙ!)
┌────┬────────────┬──────────────────────────────────┐
│ ID │ user_login │ user_pass │
├────┼────────────┼──────────────────────────────────┼
│ 2 │ victim_user│ $P$Bhash2 ← ДВОЙНОЙ ХЭШ! │
└────┴────────────┴──────────────────────────────────┴
- Имя пользователя: victim_user
- Пароль: H4cker123! но ЗАХЭШИРОВАН 2 раза
- Вход не удаётся! → Блокировка учётной записи
- Войти, используя учётные данные регистрации, если мета-данные ещё не очищены
- Или зарегистрироваться снова с тем же user_login