Что такое SQL-инъекция и функция EXTRACTVALUE

SQL-инъекция (SQLi) — это один из самых распространённых способов атаки на веб-приложения, при котором злоумышленник внедряет в запрос к базе данных произвольный SQL-код. Цель — получить доступ к данным, изменить их или выполнить другие нежелательные действия. В данной статье мы разберём конкретный пример инъекции, использующий функцию EXTRACTVALUE и оператор ELT в СУБД MySQL.

Функция EXTRACTVALUE(XML_target, XPath_expr) извлекает значение из фрагмента XML по заданному XPath-выражению. Если XPath-выражение некорректно, MySQL генерирует ошибку, в тексте которой может содержаться результат вычисления вложенного выражения. Это свойство часто используется в так называемых error-based SQL-инъекциях для извлечения данных.

Разбор payload: " ) AND EXTRACTVALUE(4746,CONCAT(0x7e,((SELECT (ELT(4746=4746,1)))),0x7e))-- -

Рассмотрим структуру запроса по частям.

  • " ) — закрывает строковый литерал и круглую скобку в оригинальном запросе, делая дальнейший код частью SQL-выражения.
  • AND — логический оператор, добавляющий условие к WHERE-клаузе.
  • EXTRACTVALUE(4746, CONCAT(0x7e, ((SELECT (ELT(4746=4746,1)))), 0x7e)) — вызов функции EXTRACTVALUE. Первый аргумент (4746) — произвольное число, которое должно быть корректным XML-документом (обычно используется для отладки). Второй аргумент — XPath-выражение, формируемое через CONCAT.
  • 0x7e — шестнадцатеричное представление символа ~ (тильда). Используется как разделитель, чтобы облегчить поиск результата в сообщении об ошибке.
  • (SELECT (ELT(4746=4746,1))) — подзапрос, возвращающий результат функции ELT. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Если N=1, возвращается '1'. Условие 4746=4746 всегда истинно, поэтому ELT возвращает '1'.
  • -- - — комментарий, обрезающий остаток исходного запроса.

В результате XPath-выражение принимает вид ~1~. При попытке разобрать его как XPath MySQL выдаёт ошибку: XPATH syntax error: '~1~'. В текст ошибки попадает значение, возвращённое подзапросом. В данном случае это константа '1', но в реальной атаке вместо неё могла бы быть, например, версия СУБД или имя пользователя.

Зачем используется ELT и CONCAT

Функция ELT позволяет выбрать одну из строк по номеру. В простейшем случае с двумя аргументами (номер и строка) она возвращает строку, если номер равен 1. Комбинация с CONCAT и тильдами создаёт строку, которая заведомо вызовет ошибку XPath, но при этом содержит полезные данные. Это классический приём error-based инъекции, описанный во многих практических руководствах по SQLi.

Например, запрос SELECT EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e)); вернёт ошибку с версией MySQL.

Какие ошибки может вызвать такой payload

При выполнении запроса с EXTRACTVALUE и некорректным XPath MySQL возвращает ошибку с кодом 1105 (HY000): XPATH syntax error: '~1~'. Если же количество столбцов в UNION-запросе не совпадает с исходным, возникает ошибка 1222 (21000): The used SELECT statements have a different number of columns. Это часто случается при попытке использовать UNION ALL без предварительного определения числа столбцов.

В нашем случае инъекция не использует UNION, поэтому ошибка 1222 маловероятна. Однако если исходный запрос возвращает несколько столбцов, а внедряемое выражение — один, может возникнуть несоответствие. Важно понимать, что error-based инъекции работают только тогда, когда приложение выводит сообщения об ошибках базы данных пользователю. В противном случае атакующий не увидит результат.

Как защититься от подобных атак

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

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

Стоит отметить, что функция EXTRACTVALUE устарела начиная с MySQL 5.7.6 и удалена в MySQL 8.0. Однако в старых версиях она по-прежнему представляет угрозу.

Вывод

Рассмотренный payload — типичный пример error-based SQL-инъекции, эксплуатирующей функцию EXTRACTVALUE для извлечения данных через сообщения об ошибках. Понимание механизма таких атак помогает разработчикам и администраторам правильно выстраивать защиту. Никогда не используйте подобные конструкции на реальных системах без разрешения — это незаконно.

Источники