Что такое SQL-инъекция через ExtractValue?

SQL-инъекция (SQL injection) — один из самых распространённых способов атаки на веб-приложения, при котором злоумышленник внедряет вредоносный SQL-код в запросы к базе данных. Существует несколько типов таких атак: union-based, boolean-based, time-based и error-based. Последний тип, error-based, основан на извлечении данных через сообщения об ошибках, которые возвращает СУБД. Функция ExtractValue в MySQL часто используется именно для error-based инъекций.

В запросе пользователя: %'))) AND EXTRACTVALUE(4070,CONCAT(0x7e,((SELECT (ELT(4070=4070,1)))),0x7e))-- - — представлен классический пример error-based SQL-инъекции. Давайте разберём его по частям.

Структура payload

Payload состоит из нескольких частей:

  • %'))) — закрывающие символы, которые пытаются завершить оригинальный SQL-запрос, чтобы внедрить свой код. Символ % — это URL-кодирование пробела, а ' — закрывающая кавычка для строкового литерала. Скобки закрывают возможные открытые скобки в исходном запросе.
  • AND EXTRACTVALUE(4070,CONCAT(0x7e,((SELECT (ELT(4070=4070,1)))),0x7e)) — основная часть инъекции. Функция EXTRACTVALUE(XML_frag, XPath_expr) извлекает значение из XML-фрагмента по заданному XPath-выражению. Если XPath-выражение некорректно, MySQL генерирует ошибку, в тексте которой выводится переданное значение.
  • -- - — комментарий, который обрезает оставшуюся часть оригинального запроса.

Функция EXTRACTVALUE

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

В нашем payload первый аргумент — 4070 (просто число, не XML), но это не важно, так как ошибка возникает на этапе разбора XPath. Второй аргумент — CONCAT(0x7e, ((SELECT (ELT(4070=4070,1)))), 0x7e). Здесь 0x7e — это шестнадцатеричное представление символа ~ (тильда). CONCAT объединяет тильду, результат подзапроса и ещё одну тильду. В итоге XPath-выражение начинается с ~, что недопустимо, и MySQL выдаёт ошибку, содержащую этот XPath, то есть нашу строку с данными.

Подзапрос с ELT

ELT(N, str1, str2, ...) — функция, возвращающая N-й элемент из списка строк. В нашем случае ELT(4070=4070, 1). Выражение 4070=4070 всегда истинно, то есть равно 1. Значит, ELT вернёт первый элемент — 1. Подзапрос (SELECT (ELT(4070=4070,1))) вернёт 1. Таким образом, CONCAT соберёт строку ~1~. При вызове EXTRACTVALUE с таким XPath MySQL выдаст ошибку: XPATH syntax error: '~1~'. Это простейший пример, демонстрирующий работу метода. В реальной атаке вместо 1 подставляются имена таблиц, колонок или другие данные, извлекаемые из базы.

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

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

  • версию MySQL (version()),
  • имя текущего пользователя (user()),
  • имя базы данных (database()),
  • имена таблиц и колонок из information_schema,
  • непосредственно данные (логины, пароли, персональную информацию).

Пример извлечения версии: AND EXTRACTVALUE(1, CONCAT(0x7e, version(), 0x7e)) — в ошибке появится версия СУБД.

Ошибка 1105 и её роль

MySQL возвращает ошибку с кодом 1105 (ER_UNKNOWN_ERROR) для ошибок XPath. В сообщении будет текст: XPATH syntax error: '~...~'. Именно этот текст и содержит извлечённые данные. Если приложение выводит ошибки базы данных пользователю, злоумышленник может их прочитать. Если ошибки скрыты, атака может не сработать, но в некоторых случаях данные попадают в логи.

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

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

  • Экранирование специальных символов (хотя это менее надёжно, чем параметризация).
  • Ограничение прав пользователя базы данных: не давайте приложению прав на чтение information_schema без необходимости.
  • Отключение вывода ошибок СУБД в продакшене: настройте display_errors = Off и логирование ошибок в файл, недоступный извне.
  • Использование WAF (Web Application Firewall) для фильтрации подозрительных запросов.
  • Регулярное обновление MySQL, так как в новых версиях некоторые функции могут быть удалены или изменены (например, в MySQL 8.0 функция EXTRACTVALUE устарела).

Заключение

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