Предисловие
В своей работе мы используем MariaDB и ранее никаких проблем с ее работой не было.
Нет ничего лучше с утра в понедельник, чем чашечка бодрящего кофе крик программиста – "у нас на локалке не импортируется база с продакшена!" Это реально бодрит. Грешным делом даже подумал – не вирусы ли нам подкинули? Учитывая что на локальной машине среда развернута точно такая же, что и на продакшене... Ну, почти такая же...
Расследование
Первая строка дампа SQL содержала очень странную строку:
/*!999999\- enable the sandbox mode */
-- MariaDB dump 10.19 Distrib 10.11.8-MariaDB, for Linux (x86_64)
--
-- Host: localhost Database: test.ru
-- ------------------------------------------------------
-- Server version 10.11.8-MariaDB
Да ладно? Это что такое? Что за sandbox mode?
Сравнил версии базы данных на сервере и на локалке.
На сервере
mariadb Ver 15.1 Distrib 10.11.8-MariaDB, for Linux (x86_64) using EditLine wrapper
На локальном компьютере:
mariadb Ver 15.1 Distrib 10.11.7-MariaDB, for Linux (x86_64) using EditLine wrapper
Ну не могли же в минорной версии поломать совместимость экспорта и импорта?
Пришлось изучать интернет в поисках ответа и даже грешным делом спрашивать chatGPT. chatGPT сморозил чушь, которую даже не хочется приводить. В общем-то не удивительно – за новостями он особо не следит....
В интернете тоже сразу не удалось толком ничего нагуглить (и даже наяндексить). Пошел читать новости на сайте MariadDB.
Вау! А вот и новость от 17 мая 2024 года, которая все объясняет – https://mariadb.org/mariadb-dump-file-compatibility-change/
Кому лень читать – да, мы поломали совместимость с предыдущими версиями MariaDB а так же с MySQL при импорте и экспорте SQL дампов и теперь придется удалять первую строку из файла, созданного mysqldump (mariadb-dump), если хотите чтобы работало как раньше.
Зачем, почему и как так вышло – разберемся далее в статье. А сейчас пока голые факты и рецепты.
Изменения коснулись версий MariaDB 10.5.25, 10.6.18, 10.11.8, 11.0.6, 11.1.5, 11.2.4 and 11.4.2. Начиная с этих версий в mysqldump (mariadb-dump) появляется злополучная строка, которая при импорте в старых версиях mariadb (и всех версиях mysql) приводит к ошибке импорта ERROR at line 1: Unknown command "-"
. Удаление этой строки позволяет произвести импорт как раньше.
Рецепты удаления первой строки из дампа mysqldump (mariadb-dump)
Сразу приведу рецепты удаления первой строки, которые приведены по ссылке и добавлю еще один из комментариев:
Рецепт 1:
Можно удалить первую строку во время экспорта так:
mariadb-dump | tail +2
Рецепт 2:
Можно удалить первую строку во время импорта так:
tail +2 | mariadb
Рецепт 3 (из коментов):
Мне этот рецепт показался наиболее универсальным, потому что подходит для любых дампов – тех, которые содержат первую строку c sandbox mode и тех, которые ее не содержат.
sed -i '1{/999999.*sandbox/d}' yourfile.sql
А что случилось-то?
С чего вообще начался сыр-бор? По ссылке в статье описано как-то все мутно и невнятно. То есть закрываем какую то уязвимость и как можно скорее.... Пришлось рыть дальше.
А дальше нашлись две ооооочень интересные публикации, которые непосредственно с MariaDB не связаны, но зато связаны с MySQL, а проблемы, как оказалось, у них общие.
Для интересующихся – 17 лет небезопасному MySQL клиенту и Доверие mysqldump и небезопасному MySQL клиенту приводит к удаленному исполнению кода. Заголовки конечно кликбейтные, но давайте посмотрим в чем дело?
Исполнение кода во время импорта или через mysql клиент
Постараюсь быть максимально краток – попробуйте исполнить этот код (он легко может быть частью вашего импортируемого файла SQL):
echo "system touch testfile.txt" | mysql; ls -l
Несмотря на то, что это как бы обычный SQL файл (мы сейчас напрямую передаем текст в mysql как это происходит при импорте), действия, которые он выполняет выходят далеко за пределы работы с базой данных. Он создает файл в вашей файловой системе. А может и другие действия выполнить. Далее все ограничивается фантазией автора. И права и ограничения на пользователей базы данных вам не помогут.
Проблема заключается в том, что mysql клиент через чур доверяет импортируемому файлу, чего делать не следует. Понятно, что вы тщательно разделяете права по пользователям базы данных, но не все знают, что скрипты могут выполнять действия за пределами прав MySQL.
Оказывается об этой проблеме говорили в сообществе MariaDB в 2020 году здесь и даже в сообществе MySQL в 2007 году тут. То есть о проблеме известно еще с 2007 года (отсюда и кликбейт про 17 лет).
Помимо команды system есть еще и pager – вот иллюстрация с ним:
$ rm -f a_file; mysql; ls -l a_file
> pager touch a_file; select 1; exit;
PAGER set to 'touch a_file'
1 row in set (0.00 sec)
Bye
-rw-r--r-- 1 jgagne jgagne 0 Apr 10 14:40 a_file
В случае если это целиком ваш сервер – особо беспокоиться нечего – сам себя взламывать через скрипт импорта не будешь. А вот если на сервер имеют доступ несколько разных людей, то вектор атаки становится очень интересный...
Причем это работает в обе стороны. Например, вы можете выполнить какую-то работу на чужом сервере и забрать оттуда бекап. Или просто кто-то с вами может поделиться бекапом сайта и попросить что либо сделать – типичный сценарий на kwork и любой фриланс бирже... Сколько векторов атаки на разработчиков открывается внезапно! Хотя ни одной злонамеренной команды php, которые мы привыкли тщательно проверять там не будет – никто же не подумает что, в файле импорта msqyl была такая команда, которая может вмешаться в работу вашей системы. И причем после самого импорта полученная база будет абсолютно чистой!
Думаю что некоторые конфигурации виртуальных серверов могут оказаться под реальной угрозой – это нужно учитывать и перепроверить безопасность.
Особенно в рамках понимания того факта, что до сих пор абсолютное большинство виртуальных (shared) хостингов все еще используют MySQL 5.7, чья поддержка завершилась практически год назад (осенью 2023).
Что делать?
Самый кардинальный и правильный способ предложила MariaDB – они ввели специальный режим sandbox mode, который включается с помощью аргумента --sandbox
в mariadb клиенте или с помощью той самой пресловутой строки \-
которая ломает импорт на старых клиентах.
Причем если с первым аргументом все понятно и очевидно – хочешь дополнительной безопасности? Используй аргумент! Но вот с первой строкой которую генерирует команда mariadb-dump и которую на момент публикации статьи нельзя было отключить, мне решительно не понятно – можно же было поступить точно так же – добавить специальный аргумент, который либо включает либо отключает эту окаянную строку?
Кстати в одном из комментариев сказано, что якобы команда MariaDB уже пришла к какому-то решению, которое не будет настолько сильно ломать совместимость. Правда мне не удалось найти никакой информации об этом.
Для mysql клиента есть один не очень очевидный аргумент, который можно использовать при импорте файлов --binary-mode
. Неизвестно по какой причине – то ли так задумано, то ли случайно, но он помогает избежать нежелательного поведения при импорте файлов.
Если нужно исправить поведение самого mysql клиента, то можно использовать замещающий скрипт, который запретит создание подпроцессов. Подробнее описано здесь.
Выводы
Учитывайте что всякий импортируемый скрипт MySQL может быть небезопасен для вашей системы и ему открыто значительно больше, чем просто база данных вашей системы. Используйте способы, описанные выше, а лучше переходите на MariaDB новых версий, чтобы избежать нежелательных последствий.
Внятной реакции от MySQL пока нет, хотя Jean-François Gagné уже сделал им баг-репорт и все еще ждет ответа.
Надеюсь, что все кто начнет сталкиваться с ошибкой импорта MySQL файлов созданных с помощью новых версий MariaDB попадут на эту статью на хабре и сумеют решить свои проблемы максимально быстро.
Если у вас есть свои соображения по этому поводу – добро пожаловать в комментарии. Если будет новая информация по этому поводу – буду обновлять статью. Постараюсь всех держать в курсе ситуации с этим поведением mysql и mariadb.
Комментарии (9)
karrakoliko
25.06.2024 15:31+1Спасибо!
Сегодня столкнулись с тем что импорт вдруг внезапно сломался.Благодаря тому что читал вашу статью, вспомнил, быстро починили.
9982th
По ссылке:
Баг создан в 2020, говорить о нем начали в 2021, к обсуждению конкретных деталей перешли в 2022, потом все опять замерло до 2024. Забавно на этом фоне выглядит текст новости
progreccor Автор
Да меня тоже этот факт поразил. Год поправлю.
petropavel
Там комбинация разных ситуаций и тикетов.
юзеры просили "sandbox mode", это как раз и есть MDEV-21778, чтобы можно было ставить mariadb как login shell и чтоб можно было давать
sudo mariadb
не давая полный рут шелл. Это старый тикет, там ничего срочного не было, просто фичу просилиmariadb-dump доверял серверу и писал его ответы в дамп, без проверок и валидации. Таким образом в дамп могли попасть команды, если плохой сервер их туда подсунет. Это MDEV-33727 — вот он новый и был новый
Оракл выпускает новый релиз MySQL в котором он фиксит CVE-2024-21096
В результате нам (MariaDB) тоже пришлось срочно это дело закрывать и мы закрыли его через sandbox mode, заодно закрыв и первый тикет.
Sabin
Можете вообще про эту историю подробнее рассказать, как разработчик? И я правильно понимаю, что на shared хостингах можно было иметь доступ к файлам остальных пользователям, например из-за этой уязвимости?
progreccor Автор
Все зависит от конфигурации и разрешений, которые дает shared хостинг своим пользователям. Учитывая что на многих хостингах до сих пор еще стоит MySQL 5.7 – думаю нас ждет множество взломов по типу 1gb и reg ru
petropavel
Про что рассказать, в чём дыра? Это уже не секрет, вот, Оракл демонстрирует: https://github.com/mysql/mysql-server/commit/f351ea92a5a0
Вкратце, суть в том, что если у плохиша есть полный контроль над сервером или он может делать MitM (потому что SSL не включён или сертификаты не проверяются), то он может подсовывать в дамп разные команды. Потому что
mariadb-dump
/mysqldump
не проверяет, что ему приходит. И тогда если кто-то этот дамп потом прочтёмmysql
клиентом, то команды выполнятся.Это довольно маловероятный сценарий, в котором юзер не доверяет своему серверу. Но теоретически возможный.
На shared хостингах — нет, только если получить полный контроль над базой данных других пользователей. Но тогда как бы доступ ко всем данным и так есть.