Что такое EXTRACTVALUE и при чём здесь SQL-инъекции?
Функция EXTRACTVALUE в MySQL предназначена для извлечения значения из XML-документа по заданному XPath-выражению. Однако из-за особенностей обработки ошибок она стала популярным инструментом для проведения error-based SQL-инъекций. Злоумышленники заставляют базу данных выдать сообщение об ошибке, содержащее конфиденциальные данные, например, имена таблиц, столбцов или хэши паролей.
В запросе пользователя: %"))) AND EXTRACTVALUE(7484,CONCAT(0x7e,((SELECT (ELT(7484=7484,1)))),0x7e))-- - — как раз демонстрируется классический пример такой инъекции. Давайте разберём его по частям.
Анатомия инъекции
Строка состоит из нескольких компонентов:
%")))— часть исходного запроса, которая закрывает предыдущие конструкции (кавычки, скобки).AND EXTRACTVALUE(7484,CONCAT(0x7e,((SELECT (ELT(7484=7484,1)))),0x7e))— сама полезная нагрузка.-- -— комментарий, обрезающий остаток оригинального SQL-запроса.
Цель — заставить MySQL выполнить подзапрос и вывести его результат в сообщении об ошибке.
Как работает EXTRACTVALUE в контексте атаки
Синтаксис функции: EXTRACTVALUE(XML_document, XPath_expression). Если XPath-выражение некорректно, MySQL генерирует ошибку вида: XPATH syntax error: '...'. В эту ошибку попадает часть переданного XPath. Злоумышленник конструирует XPath так, чтобы в него попали данные из базы.
В нашем примере вторым аргументом идёт CONCAT(0x7e,((SELECT (ELT(7484=7484,1)))),0x7e). 0x7e — это тильда (~), используемая как маркер начала и конца выводимых данных. ELT(7484=7484,1) возвращает строку '1', так как условие 7484=7484 истинно. Фактически это простейший тест: если инъекция работает, в ошибке появится ~1~.
Почему используется ELT?
ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае ELT(7484=7484,1) вернёт '1', потому что условие истинно (1). Это позволяет создавать условные конструкции: если условие ложно, ELT вернёт NULL, и ошибка может не содержать данных. Такой подход часто применяется для слепых инъекций, но в error-based он служит для проверки работоспособности.
Пошаговый разбор примера
- Закрытие предыдущих конструкций:
%")))— предполагается, что исходный запрос содержал незакрытые кавычки и скобки. Символ%может быть частью URL-кодирования. - Добавление условия AND: чтобы инъекция сработала, нужно, чтобы левая часть выражения была истинной. Если исходный запрос возвращает результаты, добавление
AND ...не нарушит логику, но выполнит внедрённую функцию. - Вызов EXTRACTVALUE: первый аргумент — произвольное число (7484), второй — сконкатенированная строка с тильдами и подзапросом.
- Подзапрос:
(SELECT (ELT(7484=7484,1)))— возвращает '1'. - Комментарий:
-- -отсекает всё после инъекции, чтобы синтаксис остался корректным.
В результате MySQL выполнит функцию и выдаст ошибку: XPATH syntax error: '~1~'. Это подтверждает, что инъекция возможна. Далее злоумышленник заменяет ELT(7484=7484,1) на подзапрос, извлекающий нужные данные, например: (SELECT table_name FROM information_schema.tables LIMIT 0,1).
Реальные примеры извлечения данных
Для получения имён таблиц используется запрос к information_schema.tables. Например:
AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1), 0x7e))
В ошибке появится имя первой таблицы. Аналогично можно извлечь столбцы, логины и пароли.
Более сложные варианты используют CONCAT_WS, GROUP_CONCAT и другие функции для объединения данных в одну строку.
Защита от error-based SQL-инъекций
Основные меры:
- Параметризованные запросы (prepared statements): самый надёжный способ, при котором данные не попадают в текст SQL.
- Экранирование специальных символов: но это менее надёжно, чем параметризация.
- Отключение вывода ошибок СУБД на продакшене: чтобы злоумышленник не видел сообщения с данными.
- Использование ORM: современные ORM обычно используют параметризацию.
- Регулярные аудиты безопасности и сканеры уязвимостей.
Важно понимать, что EXTRACTVALUE — не единственная функция для error-based инъекций. Также используются UPDATEXML, GTID_SUBSET, EXP и другие. Однако EXTRACTVALUE и UPDATEXML наиболее популярны из-за явного вывода данных в тексте ошибки.
Заключение
Строка %"))) AND EXTRACTVALUE(7484,CONCAT(0x7e,((SELECT (ELT(7484=7484,1)))),0x7e))-- - — это пример эксплойта для error-based SQL-инъекции в MySQL. Она демонстрирует, как можно заставить базу данных выдать данные через сообщение об ошибке. Понимание таких техник необходимо для разработки безопасных приложений и защиты от атак. Всегда используйте параметризованные запросы и не выводите ошибки СУБД конечным пользователям.
Комментарии
—Войдите, чтобы оставить комментарий