
MySQL Community Server 26.7.0 — высокий — mysqlbinlog --raw Rotate path leftover — запись файла на клиенте
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · mysql-mysqlbinlog-raw-path
Класс: запись файла (клиент) Достижимость: удалённая (UI:R)
MySQL Community Server mysqlbinlog 26.7.0 (06a5c1c) — Oracle
mysqlbinlog --raw --read-from-remote-server копирует new_log_ident события Rotate в log_file_name без проверки базового имени. Следующее событие FORMAT_DESCRIPTION вызывает my_fopen для этого пути и записывает BINLOG_MAGIC вместе с событием. Враждебный дамп, отправляющий настоящий ident Rotate с /, записывает этот файл от имени UID клиента.
--raw — это документированное копирование удалённого binlog-файла. Ошибка в том, что ident трактуется как путь.
| ID | CVE пока нет |
| Класс | Запись файла (клиент --raw BINLOG_MAGIC) |
| Достижимость | Удалённая (жертва запускает mysqlbinlog --raw -R против дампа атакующего; UI:R) |
| CWE | CWE-22 |
| CVSS | High: 8.1 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N |
| Продукт | MySQL Community Server mysqlbinlog |
| Затронуто | 26.7.0 (06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8) |
| Аутентификация | жертва запускает mysqlbinlog --raw -R против дампа атакующего |
| Лицензия | GNU Affero GPL v3.0 |
| Лаборатория | только 127.0.0.1. Файл-свидетель с BINLOG_MAGIC. Запись файла, не RCE. |
Поднять сервер с протоколом MySQL. Обработать COM_BINLOG_DUMP. Отправить совпадающий поддельный Rotate (timestamp 0, ident равен запрошенному имени лога), чтобы дамп не остановился. Отправить настоящий Rotate (timestamp != 0), ident которого равен /abs/path. Отправить событие FORMAT_DESCRIPTION.
Оператор, запустивший mysqlbinlog --raw -R ... mysql-bin.000001, запишет /abs/path от имени UID клиента. Содержимое — байты binlog (\xfebin плюс событие FD), а не произвольная полезная нагрузка. Перезапись любого пути, который может создать этот UID.
Настоящий mysqld не выдаст ident Rotate с /. Ошибка на стороне клиента.
Та же охота на 26.7.0, что и mysqldump SHOW TABLES overflow и mysqldump --tab path. Демон по умолчанию был пуст. Клиентские утилиты по-прежнему доверяли удалённым именам.
if (raw_mode) {
if (output_file != nullptr) {
snprintf(log_file_name, sizeof(log_file_name), "%s%s", output_file,
rev->new_log_ident);
} else {
my_stpcpy(log_file_name, rev->new_log_ident);
}
}
Поддельный Rotate (when.tv_sec == 0), ident которого не совпадает с запрошенным логом, останавливает дамп. Совпадающий поддельный Rotate пропускается (continue) после копирования. Настоящий Rotate не останавливает. Следующий FD:
if (!(result_file = my_fopen(
log_file_name, O_WRONLY | MY_FOPEN_BINARY, MYF(MY_WME)))) {
error("Could not create log file '%s'", log_file_name);
Временные файлы LOAD DATA остаются SQL_LOAD_MB в tmpdir. Закрыто. Длина ident ограничена FN_REFLEN-1. / не удаляется.
Уже зафиксированные неверные пути: отправка поддельного Rotate, ident которого является путём (дамп останавливается); использование --result-file (ident становится префиксом, другая ошибка); настоящий mysqld в качестве оракула; контрольные суммы оставлены включёнными.
cd lab
./run.sh
Образ mysql:26.7.0. Бинарник /usr/libexec/mysqlsh/mysqlbinlog Ver 26.7.0 (не в PATH в этом образе). Контрольный стенд: поддельный Rotate mysql-bin.000001 плюс FD записывает work/mysql-bin.000001. Стенд обхода: совпадающий поддельный Rotate, настоящий Rotate с ident /work/oracle/MYSQL-BINLOG-RAW-WITNESS, FD записывает этот путь (BINLOG_MAGIC). Опубликованы 127.0.0.1:18620 / 18621. Привяжите к loopback. Запись файла с байтами binlog, не RCE. Без --result-file.
control-basename=yes
traversal-outside=yes
SUCCESS mysql-mysqlbinlog-raw-path ... MYSQL-BINLOG-RAW-WITNESS
Взять basename от new_log_ident перед my_stpcpy / snprintf в log_file_name. --raw должен писать в cwd или в префикс --result-file, а не в ident с /.
06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8)client/mysqlbinlog.cc dump_remote_log_entries