Что такое EXTRACTVALUE и при чём тут SQL-инъекция?

Строка ')))) AND EXTRACTVALUE(3903,CONCAT(0x7e,((SELECT (ELT(3903=3903,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции для СУБД MySQL. Она предназначена для извлечения данных из базы через вывод сообщения об ошибке, которое возвращает сервер.

Функция EXTRACTVALUE() в MySQL используется для извлечения значения из XML-документа по заданному XPath-выражению. Однако при передаче некорректного XPath-выражения она генерирует ошибку, в тексте которой может содержаться переданная строка. Злоумышленники используют это для получения информации из базы данных.

Как работает этот конкретный запрос?

Разберём по частям:

  • ')))) — закрывающие скобки и кавычки, которые завершают предыдущий SQL-запрос и позволяют внедрить свой код.
  • AND EXTRACTVALUE(3903,CONCAT(0x7e,((SELECT (ELT(3903=3903,1)))),0x7e)) — вызов функции EXTRACTVALUE с двумя аргументами: первый — число 3903, второй — конкатенация тильды (0x7e), результата подзапроса и ещё одной тильды.
  • -- - — комментарий, который отсекает оставшуюся часть оригинального запроса.

Внутри подзапроса SELECT (ELT(3903=3903,1)) проверяется условие 3903=3903 (всегда истина), и функция ELT() возвращает первый элемент из списка, то есть 1. Это простейший пример, который можно заменить на извлечение реальных данных, например, версии базы или имени пользователя.

Что происходит при выполнении?

MySQL пытается выполнить EXTRACTVALUE(3903, '~1~'). Поскольку первый аргумент не является корректным XML-документом, функция возвращает ошибку вида: XPATH syntax error: '~1~'. В этом сообщении об ошибке отображается переданная строка — в данном случае ~1~. Если вместо 1 подставить, например, SELECT version(), то в ошибке появится версия MySQL.

Зачем это нужно злоумышленникам?

Error-based SQL-инъекции позволяют получать данные из базы, даже если приложение не выводит результаты запроса напрямую. Сообщения об ошибках часто отображаются в браузере или возвращаются в ответе API. Это делает атаку простой и эффективной.

С помощью таких инъекций можно извлечь:

  • версию СУБД;
  • имя текущего пользователя базы данных;
  • названия таблиц и столбцов;
  • содержимое таблиц (логины, пароли, персональные данные).

Примеры других error-based функций

Помимо EXTRACTVALUE, в MySQL существуют и другие функции, вызывающие ошибки с полезной нагрузкой:

  • UPDATEXML() — аналогична EXTRACTVALUE, но также используется для внедрения XPath-ошибок.
  • GTID_SUBSET() — в некоторых версиях MySQL вызывает ошибку с переданными данными.
  • EXP() — при передаче большого числа вызывает ошибку переполнения, которая может содержать данные.

Все они эксплуатируют одну и ту же идею: заставить СУБД выдать сообщение об ошибке, содержащее результат подзапроса.

Как защититься от таких инъекций?

Основной метод защиты — использование параметризованных запросов (prepared statements). Они разделяют код SQL и данные, поэтому внедрение становится невозможным.

Дополнительные меры:

  1. Экранирование специальных символов (но это менее надёжно, чем параметризация).
  2. Ограничение прав пользователя базы данных: не давайте приложению прав на чтение системных таблиц.
  3. Отключение вывода ошибок СУБД в production-окружении. Сообщения об ошибках должны логироваться, но не показываться пользователю.
  4. Использование WAF (Web Application Firewall) для фильтрации подозрительных запросов.
  5. Регулярное обновление СУБД и фреймворков.

Заключение

Запрос ')))) AND EXTRACTVALUE(3903,CONCAT(0x7e,((SELECT (ELT(3903=3903,1)))),0x7e))-- - — это учебный пример error-based SQL-инъекции. Он демонстрирует, как через функцию EXTRACTVALUE можно извлечь данные из MySQL, используя сообщения об ошибках. Понимание таких атак помогает разработчикам и администраторам лучше защищать свои приложения.

Источники