
phpMyAdmin 5.2.3 — высокий уровень — удалённо — остаточный — setup/validate всё ещё доступен
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-setup-validate
Разбор: https://abraxaslabs.tech/research/phpmyadmin-setup-validate
Класс: SSRF Доступ: Удалённый
phpMyAdmin 5.2.3 (тег RELEASE_5_2_3, коммит 962857e). setup/index.php завершает работу, если присутствует config.inc.php. setup/validate.php — нет. Он по-прежнему загружается в рамках $isMinimumCommon, берёт CSRF-токен с публичной страницы входа и вызывает Validator::testDBConnection -> mysqli_connect к хосту, порту, пользователю и паролю из поля JSON values.
Неаутентифицированный клиент выполняет GET /, чтобы получить сессионную cookie и токен, затем отправляет POST на setup/validate.php с id=Server и выбранными им Servers/1/host и Servers/1/port. Хост phpMyAdmin открывает TCP-рукопожатие MySQL к этому адресу. Это SSRF поверх протокола MySQL: внутренний 3306, перебор учётных данных против внутреннего сервера, оракул портов по времени отклика и ошибкам mysqli. Это не SSRF к HTTP-метаданным, если только что-то на этом порту не говорит на MySQL. hide_db также подставляет пользовательское регулярное выражение в preg_match. Я не запускал этот путь ReDoS в данной лаборатории.
Официальный образ phpmyadmin:5.2.3 удаляет setup/. Эта уязвимость актуальна только тогда, когда этот каталог всё ещё находится в корне веб-сервера, что является распространённым остатком после установки. Лаборатория восстанавливает setup/ из архива 5.2.3, чтобы версия соответствовала RELEASE_5_2_3.
PMASA-2016-44 / CVE-2016-6621 охватывал часть SSRF в setup. Проверка «отключить setup при наличии конфигурации» так и не была применена к validate.php / config.php.
| ID | CVE пока нет |
| Класс | SSRF (протокол MySQL) |
| Доступ | Удалённый (неаутентифицированный, если setup/ всё ещё доступен через веб) |
| CWE | CWE-918 |
| CVSS | Высокий: 7.2 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N |
| Продукт | phpMyAdmin |
| Затронуто | 5.2.3 тег RELEASE_5_2_3 (962857e) при setup/ всё ещё в docroot |
| Аутентификация | Не требуется. CSRF-токен с публичной страницы входа. Вход в MySQL не требуется. |
| Лицензия | GNU Affero GPL v3.0 |
| Лаборатория | только 127.0.0.1:19230 |
Любой, кто может достучаться до оставшегося дерева setup/, может заставить хост phpMyAdmin открыть TCP-соединение по протоколу MySQL к выбранному им хосту и порту.
| Привилегия | Метод / путь | Доказано в лаборатории или предполагается |
|---|---|---|
| Открыть TCP с хоста PMA к хосту:порту атакующего (целостность исходящего соединения; разведка этого порта) | Неаутентифицированный POST /setup/validate.php id=Server с Servers/1/host + Servers/1/port и токеном из GET / | Доказано в лаборатории. Оракул на oracle:13306 зафиксировал PMA-SETUP-VALIDATE-WITNESS от контейнера PMA |
| Подтвердить, что UI setup отключён, а validate продолжает работать | GET /setup/index.php | Доказано в лаборатории. Тело содержит "setup is disabled" / configuration already exists |
| Отказ при отсутствии CSRF-токена со страницы входа | Тот же POST без token | Доказано в лаборатории. Ноль попаданий в оракул |
| Оракул портов / учётных данных по ошибкам mysqli и времени отклика | Тот же testDBConnection | Предполагается. Тело ответа в лаборатории было mysqli_connect(): (HY000/2006): MySQL server has gone away после того, как оракул принял соединение, а затем закрыл его |
| Обратиться по протоколу MySQL к внутреннему 3306 и попробовать отправленные пользователя/пароль | Тот же mysqli_connect | Предполагается. Не направлялось на сервис db лаборатории |
ReDoS через validateRegex, подставляющий пользовательское регулярное выражение | id=Servers/1/hide_db | Предполагается. Не проверялось |
Закрыто в этой лаборатории: SSRF через HTTP-метаданные (рукопожатие — это MySQL, а не GET /latest/meta-data), неаутентифицированный вход в PMA, OS shell и сам мастер установки (index.php остаётся отключённым). FAIL, если setup/ не развёрнут (по умолчанию в официальном образе).
Восемь параллельных поисков исходников RELEASE_5_2_3. В setup/index.php есть фатальная ошибка при существовании конфига. В setup/validate.php — нет. setup/lib/common.inc.php устанавливает $isMinimumCommon и не ищет CONFIG_FILE.
Неверные пути: считать официальный образ этим остатком (он удаляет setup/); отправлять POST без токена со страницы входа (ноль попаданий в оракул); считать это SSRF через HTTP-метаданные (рукопожатие — это MySQL).
python3 phpmyadmin-setup-validate-Abraxas-Labs.py
или
cd lab
./run.sh
Только loopback: http://127.0.0.1:19230. Проект Compose phpmyadmin-setup-validate. Dockerfile восстанавливает setup/ из tarball 5.2.3 и запускает TCP-оракул на порту 13306. Свидетель PMA-SETUP-VALIDATE-WITNESS.
SUCCESS phpmyadmin-setup-validate how=live tcp=yes setup-index-disabled=yes PMA-SETUP-VALIDATE-WITNESS
Поместите фатальную проверку file_exists(CONFIG_FILE) в setup/lib/common.inc.php, чтобы каждый скрипт установки завершался с ошибкой. Ограничьте хосты в testDBConnection. Не создавайте разделители preg_match из пользовательских строк.
962857e)setup/index.php фатальная ошибка при существующем конфигеsetup/validate.php отсутствие этой проверкиlibraries/classes/Config/Validator.php testDBConnection / mysqli_connectGNU Affero GPL v3.0. См. LICENSE. Только для лабораторной среды с loopback. Без гарантий.