Содержание статьи

Всем привет. Как часто ты натыкаешься на скрипты администрирования MySQL? Лично я — постоянно. То Adminer проскочит, то старичок Sypex dumper промелькнет на периметре. Или, может быть, тебе попался скрипт, который может импортировать данные из сторонней БД? В общем, если у тебя есть возможность коннекта из приложения к своему серверу MySQL, то считай, что у тебя в кармане как минимум читалка файлов.

 

Intro

Техника, о которой я хочу сейчас рассказать, — это особенность протокола MySQL. Поэтому фиксить ее, сам понимаешь, никто не торопится. Шутка ли, эксплуатация этой фичи находится в паблике с 2013 года.

В MySQL есть конструкция LOAD DATA LOCAL INFILE 'filename', с помощью которой можно импортировать в таблицу локальные (клиентские) файлы. Нам нужно посмотреть, как же она работает на пакетном уровне. Для этого я вооружился tcpdump’ом, чтобы лучше их слышать, и Wireshark’ом, чтобы лучше их видеть. Присоединился к тестовому MySQL, выполнил команду LOAD DATA LOCAL INFILE '/etc/passwd' INTO TABLE test FIELDS TERMINATED BY '\n';, посмотрел результат импорта и вежливо попрощался с сервером.

 

Подробнее

Теперь все внимание на Wireshark. Авторизацию и прочие нежности опустим и сразу перейдем к пакету с запросом, точнее к ответу от сервера на него:

0000   0c 00 00 01 fb 2f 65 74 63 2f 70 61 73 73 77 64  ...../etc/passwd

Оп! А следующим пакетом клиент возвращает содержимое файла /etc/passwd. Получается так, что сервер просто говорит клиенту: 0xFB Вообще-то я здесь для того, чтобы увидеть содержимое %filename%. И клиент послушно выполняет команду.

Запроса сервера на получение файла от клиента
Запроса сервера на получение файла от клиента

В этом и есть суть «уязвимости». Нам нужно создать фейковый MySQL-сервер, который бы авторизовывал клиента, отправлял пакет FB с интересующим именем файла и выводил ответ от клиента.

Исходный код такого сервера можешь найти в моем GitHub. Это форк сервера от Gifts (за что ему огромное спасибо), заточенный под современные версии MySQL. В исходнике можно указать путь до файла, который нужно прочитать, и порт фейк-сервера.

Теперь несколько слов о PHP и драйвере для работы с MySQL — mysqlnd. Если используется такой драйвер, а он по умолчанию используется с PHP 5.4, то при чтении файлов можно применять врапперы PHP. И читалка медленно превращается в почти полноценную SSRF.

Использование враппера base64-encode при чтении
Использование враппера base64-encode при чтении
 

Ложка дёгтя

Если в приложении для работы с БД используется PDO, то фича, к сожалению, не работает. В нем по умолчанию отключено выполнение LOAD DATA LOCAL INFILE.

Если приложение написано на Python и в качестве клиента выступает модуль MySQLdb, то чтение файлов также невозможно, если при соединении не указан аргумент local_infile. Однако при использовании mysql.connector все работает прекрасно.

Чтение файла с помощью Adminer
Чтение файла с помощью Adminer

Стоит также отметить, что все сказанное актуально и для MariaDB, так как протоколы общения в данном случае идентичны.

Все на сегодня. Исследуй эту тему, возможно наткнешься на что-то интересное. Желаю удачных аудитов!

Комментарии

Подпишитесь на ][, чтобы участвовать в обсуждении

Обсуждение этой статьи доступно только нашим подписчикам. Вы можете войти в свой аккаунт или зарегистрироваться и оплатить подписку, чтобы свободно участвовать в обсуждении.

Check Also

Хакер ищет авторов. Читатель? Хакер? Программист? Безопасник? Мы тебе рады!

Восемнадцать лет мы делаем лучшее во всем русскоязычном пространстве издание по IT и инфор…