phpMyAdmin 5.2.3 — высокий — удалённый — 2FA — config/set очищает двухфакторную аутентификацию
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-config-set-2fa
Разбор: https://abraxaslabs.tech/research/phpmyadmin-config-set-2fa
Класс: Остаточные привилегии / отсутствие step-up Доступ: Удалённый
phpMyAdmin 5.2.3 (RELEASE_5_2_3 / 962857e) - phpMyAdmin
POST index.php?route=/config/set записывает любую настройку из белого списка, включая 2fa. UserPreferences::persistOption не выполняет никакой проверки. Settings -> Two-factor по-прежнему вызывает TwoFactor::check(true), прежде чем снять фактор. /config/set этого не делает.
Аутентифицированная сессия или XSS/CSRF, способный отправить POST с токеном страницы, может передать key=2fa и value=null. При следующем входе по паролю не будет запроса TOTP, WebAuthn или Simple. Это устойчивое удаление, а не пропуск на один запрос.
| ID | CVE пока нет |
| Класс | Остаточные привилегии / отсутствие step-up |
| Доступ | Удалённый (вход по cookie; требуется CSRF-токен) |
| CWE | CWE-620 |
| CVSS | Высокий: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| Продукт | phpMyAdmin |
| Затронуто | 5.2.3 тег RELEASE_5_2_3 (962857e4f63d42e38f11ff4d63f5e722018add76) |
| Аутентификация | вход по cookie. Требуется CSRF-токен. Доводит XSS или CSRF до устойчивого удаления 2FA |
| Лицензия | GNU Affero GPL v3.0 |
| Лаборатория | только 127.0.0.1 |
Снять 2FA с учётной записи phpMyAdmin, не предъявляя TOTP, WebAuthn или поле подтверждения Simple. Следующий вход по паролю будет только по паролю. Полный PMA от имени этого пользователя MySQL (SQL, пользователи, экспорт).
| Привилегия | Метод / путь | Разведка / целостность / доступность | Доказано в лаборатории или выведено |
|---|---|---|---|
Сохранить 2fa как null и удалить второй фактор из pmadb | Аутентифицированный POST index.php?route=/config/set key=2fa value=null плюс валидный token | Целостность хранилища настроек | Доказано в лаборатории. success:true, pmadb config_data стал [] |
| Войти только по паролю после этой записи | Новая cookie-сессия, тот же пользователь MySQL | Целостность пути входа | Доказано в лаборатории. Без 2fa_confirm, попал в обычный интерфейс |
| Сохранить текущую сессию, пока 2FA исчезает для последующих входов | Тот же обработчик; persistOption записывает в хранилище, а не в живой флаг two_factor_check | Целостность последующих сессий | Доказано в лаборатории. Сессия A осталась. Сессия B видела 2FA. Сессия C — нет |
| Цепочка от хранимого XSS или CSRF, способного отправить POST с токеном страницы | Остатки того же ревью, не эта лаборатория | Целостность 2FA после same-origin POST | Выведено |
| Удалить 2FA через Settings | POST /preferences/two-factor 2fa_remove=1 | Целостность 2FA через документированный интерфейс | Доказано в лаборатории как закрыто. Без фактора PMA показывает страницу подтверждения, а в pmadb по-прежнему backend=simple |
Закрыто в этом остатке: неаутентифицированный доступ, обход пароля MySQL, OS RCE, чтение строк pmadb других пользователей. Мне не понадобился остаток #1 (подпись CustomServer). Я не обходил пароль MySQL.
Тот же пин: остаток WebAuthn CustomServer.
Я закрепил 5.2.3 после PMASA-2025-1/2/3. Аутентификация по cookie, pmadb pma__userconfig. В лаборатории включается только $cfg['DBG']['simple2fa'], чтобы в настройках можно было зарегистрировать Simple-бэкенд без аппаратного ключа. TOTP и WebAuthn хранятся в одном и том же ключе предпочтений 2fa.
SetConfigController принимает key и JSON value и вызывает Config::setUserValue. Про UserPreferences::persistOption в документации сказано: «No validation is done!» apply() включает 2fa в белый список, чтобы ключ не отбрасывался как неизвестное предпочтение.
$result = $this->config->setUserValue(null, $key, json_decode($value));
json_decode('null') — это PHP null. Затем persistOption('2fa', null, $default) удаляет config_data['2fa'], поскольку значение по умолчанию для этого пути также равно null.
Settings -> Two-factor — это контраст. TwoFactorController не выполнит configure(''), пока TwoFactor::check(true) не вернёт true.
Уже зафиксированные неверные повороты: трактовка Settings 2fa_remove как дыры (он всё ещё требует фактор); утверждение о неаутентифицированном доступе; утверждение о пропуске пароля MySQL; трактовка этого как остатка #1 (CustomServer); обратная оболочка. Театр.
python3 phpmyadmin-config-set-2fa-Abraxas-Labs.py
# or: cd lab && ./run.sh
Нацельтесь только на http://127.0.0.1:19280. Проект Compose phpmyadmin-config-set-2fa. Закрепите RELEASE_5_2_3. run.sh копирует или клонирует этот тег в lab/src/ для образа. Стек разворачивается после запуска.
В настройках был подключён Simple 2FA. Второй браузер открыл страницу 2fa_confirm. POST 2fa_remove без фактора остался на интерфейсе подтверждения и оставил backend=simple в pmadb. Затем POST /config/set вернул success:true, pmadb стал [], и следующий вход привёл в обычный интерфейс.
SUCCESS phpmyadmin-config-set-2fa enroll=simple ui-remove-blocked=yes config-set-cleared=yes next-login-password-only=yes PMA-CONFIG-SET-2FA-WITNESS
Запретить 2fa (и другие ключи аутентификации) на /config/set. Требовать TwoFactor::check(true) перед любым изменением 2FA. Оставить путь Settings единственным местом записи.
962857e4f63d42e38f11ff4d63f5e722018add76)libraries/classes/Controllers/Config/SetConfigController.phplibraries/classes/Config/UserPreferences.phpGNU Affero GPL v3.0. См. LICENSE. Только для лаборатории на loopback. Без гарантий.