Что такое EXTRACTVALUE и при чём тут SQL-инъекция?
Строка ' AND EXTRACTVALUE(1876,CONCAT(0x7e,((SELECT (ELT(1876=1876,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции (инъекции на основе ошибок) для СУБД MySQL. Такие конструкции используют для извлечения данных из базы через сообщения об ошибках, которые возвращает сервер.
Функция EXTRACTVALUE в MySQL предназначена для работы с XML: она извлекает значение из XML-документа по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_document, XPath_expression). Если XPath-выражение некорректно, MySQL генерирует ошибку, в тексте которой отображается переданная строка. Именно это свойство и эксплуатируют злоумышленники.
Впервые массово применять EXTRACTVALUE для SQL-инъекций начали около 2010 года, когда выяснилось, что функция возвращает часть входных данных в сообщении об ошибке. Аналогичными возможностями обладают UPDATEXML() и GTID_SUBSET().
Разбор строки по частям
Рассмотрим запрос детально:
- ' — закрывающая кавычка, которая завершает строковый литерал в уязвимом запросе и позволяет внедрить произвольный SQL-код.
- AND — логический оператор, присоединяющий наше условие к исходному запросу.
- EXTRACTVALUE(1876, ...) — вызов уязвимой функции. Первый аргумент (1876) — произвольное число, которое должно быть корректным XML-документом; на самом деле оно не используется, так как ошибка возникает раньше.
- CONCAT(0x7e, ((SELECT (ELT(1876=1876,1)))), 0x7e) — конкатенация тильды (0x7e), результата подзапроса и ещё одной тильды. Тильда здесь — маркер, по которому в тексте ошибки легко найти полезную нагрузку.
- ELT(1876=1876,1) — функция ELT возвращает N-й элемент из списка. Выражение
1876=1876всегда истинно (1), поэтому ELT(1,1) вернёт 1. В реальной атаке вместо этого подзапроса подставляют, например,SELECT version()илиSELECT table_name FROM information_schema.tables. - -- - — комментарий, который «съедает» остаток оригинального SQL-запроса, чтобы он не вызвал синтаксическую ошибку.
В результате MySQL пытается вычислить XPath-выражение, начинающееся с тильды, что недопустимо. Сервер возвращает ошибку вида:
ERROR 1105 (HY000): XPATH syntax error: '~1~'
В сообщении виден результат подзапроса — в данном примере «1». В реальной атаке здесь окажутся имя базы, версия СУБД, логины и хеши паролей.
Как это работает на практике
Предположим, уязвимый запрос выглядит так:
SELECT * FROM users WHERE id = '$_GET[id]';
Передав параметр id со значением ' AND EXTRACTVALUE(1876,CONCAT(0x7e,((SELECT (ELT(1876=1876,1)))),0x7e))-- -, злоумышленник заставляет СУБД выполнить:
SELECT * FROM users WHERE id = '' AND EXTRACTVALUE(1876,CONCAT(0x7e,((SELECT (ELT(1876=1876,1)))),0x7e))-- -';
Условие id = '' ложно, но из-за оператора AND вторая часть всё равно вычисляется. EXTRACTVALUE вызывает ошибку, и её текст возвращается пользователю. Если приложение выводит ошибки MySQL, атакующий получает данные. Если вывод ошибок отключён, инъекция не сработает — это одна из базовых мер защиты.
Зачем используют ELT и CONCAT
Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В примере ELT(1876=1876,1) выражение 1876=1876 всегда истинно и равно 1, поэтому возвращается «1». Это тестовый запрос, проверяющий, уязвимо ли приложение. Если в ответе появляется ошибка с «~1~», значит, инъекция возможна.
Функция CONCAT склеивает символы. Тильда (0x7e) выбрана потому, что редко встречается в обычных данных и легко находится в тексте ошибки. Иногда вместо неё используют 0x3a (двоеточие) или 0x7c (вертикальная черта).
Опасность и последствия
Error-based SQL-инъекции через EXTRACTVALUE позволяют злоумышленнику:
- получить версию MySQL и имя текущей базы;
- извлечь имена таблиц и колонок из information_schema;
- прочитать логины, хеши паролей, персональные данные пользователей;
- в некоторых конфигурациях — выполнить произвольные команды на сервере.
По данным OWASP, SQL-инъекции стабильно входят в топ-10 критических уязвимостей веб-приложений. Ошибки, возвращаемые СУБД, — один из самых простых векторов атаки, так как не требуют сложной подготовки.
Как защититься
Основные меры профилактики:
- Параметризованные запросы (prepared statements). Это самый надёжный способ: данные передаются отдельно от SQL-кода и не могут изменить структуру запроса.
- Отключение вывода ошибок СУБД. В production-среде сообщения об ошибках MySQL не должны попадать в ответ клиенту.
- Экранирование пользовательского ввода. Если prepared statements недоступны, применяйте функции экранирования, например mysqli_real_escape_string.
- Ограничение прав пользователя БД. Учётная запись приложения не должна иметь прав на чтение information_schema или выполнение файловых операций.
- WAF и регулярные сканирования. Веб-application firewall может блокировать характерные сигнатуры вроде EXTRACTVALUE, но не заменяет исправление кода.
Важно понимать: EXTRACTVALUE — не «баг» MySQL, а штатная функция. Уязвимость создаёт код приложения, который вставляет пользовательский ввод в SQL-запрос без обработки. Поэтому исправлять нужно именно приложение, а не искать обходные пути в СУБД.
Итог
Строка ' AND EXTRACTVALUE(1876,CONCAT(0x7e,((SELECT (ELT(1876=1876,1)))),0x7e))-- - — это учебный пример error-based SQL-инъекции. Она демонстрирует, как через функцию EXTRACTVALUE и намеренно вызванную ошибку можно получить данные из базы MySQL. Понимание таких конструкций необходимо разработчикам и специалистам по информационной безопасности для защиты веб-приложений.
Комментарии
—Войдите, чтобы оставить комментарий