Введение
Встречая в логах или в поле ввода подобную строку: ) AND EXTRACTVALUE(7289,CONCAT(0x7e,((SELECT (ELT(7289=7289,1)))),0x7e))-- -, многие задаются вопросом: что это и какова её цель? Это классический пример SQL-инъекции, нацеленной на извлечение информации из базы данных MySQL с использованием функций EXTRACTVALUE и CONCAT. В данной статье мы подробно разберём, как работает эта конструкция, для чего она применяется и как от неё защититься.
Что такое SQL-инъекция?
SQL-инъекция (SQL injection) — один из самых распространённых способов атаки на веб-приложения, при котором злоумышленник внедряет произвольный SQL-код в запрос к базе данных. Это становится возможным, если приложение не проверяет должным образом пользовательский ввод и передаёт его напрямую в SQL-запрос. Успешная инъекция может привести к утечке конфиденциальных данных, изменению или удалению информации, а в некоторых случаях — к полному захвату сервера.
Разбор конструкции
Рассматриваемая строка состоит из нескольких частей. Разберём каждую.
Начальный фрагмент: ) AND ...
Символ ) закрывает скобку, которая, вероятно, была открыта в оригинальном запросе. Это позволяет «вырваться» из контекста и добавить собственные условия. Далее идёт AND — логический оператор, позволяющий присоединить дополнительное выражение к условию WHERE.
Функция EXTRACTVALUE
EXTRACTVALUE(XML_fragment, XPath_expression) — это функция MySQL (до версии 8.0.17), предназначенная для извлечения значения из XML-документа по заданному XPath-выражению. Если XML-фрагмент некорректен или XPath не соответствует ни одному узлу, функция генерирует ошибку. Именно это свойство и используется в атаках: злоумышленник может вызвать ошибку, содержащую результат подзапроса, и таким образом «вытащить» данные через сообщение об ошибке.
Функция CONCAT и шестнадцатеричные литералы
CONCAT() объединяет строки. В нашем случае она собирает строку из трёх частей: 0x7e (тильда «~»), результат подзапроса и снова 0x7e. Тильда используется как маркер, чтобы отделить выводимые данные от прочего текста ошибки и упростить их извлечение.
Подзапрос с ELT
SELECT (ELT(7289=7289,1)) — это вложенный запрос, который возвращает число 1. Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 7289=7289 — всегда истинное условие, что даёт 1, поэтому ELT(1,1) вернёт «1». В реальной атаке вместо этого подзапроса мог бы быть запрос к системным таблицам, например, для получения имени базы данных или хеша пароля.
Комментарий в конце
-- - — это комментарий в SQL (два дефиса, за которыми следует пробел или другой символ). Он «отрезает» оставшуюся часть оригинального запроса, чтобы синтаксис был корректным.
Как это работает целиком
Предположим, исходный запрос выглядел так:
SELECT * FROM users WHERE id = ('');
После подстановки вредоносной строки запрос превращается в:
SELECT * FROM users WHERE id = ('') AND EXTRACTVALUE(7289,CONCAT(0x7e,((SELECT (ELT(7289=7289,1)))),0x7e))-- -';
База данных выполняет условие AND. Функция EXTRACTVALUE пытается обработать строку, начинающуюся с тильды, как XML. Поскольку это не валидный XML, MySQL выдаёт ошибку, в тексте которой будет присутствовать переданная строка, включая результат подзапроса. Злоумышленник, анализируя ответ сервера, может увидеть эту ошибку и получить искомые данные.
Зачем это нужно злоумышленнику?
- Обход фильтров: Если приложение блокирует кавычки или другие символы, EXTRACTVALUE позволяет обойти некоторые защиты.
- Извлечение данных: С помощью подзапросов можно получать имена таблиц, столбцов, логины, пароли и другую чувствительную информацию.
- Проверка уязвимости: Даже если атака не удаётся, сам факт появления ошибки говорит о возможной уязвимости.
Пример реальной атаки
Представим, что на сайте есть форма поиска, и параметр q подставляется в SQL-запрос без экранирования. Злоумышленник может отправить:
') AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT database()),0x7e))-- -
В ответе сервера появится ошибка с именем текущей базы данных. Затем аналогично можно извлечь таблицы, столбцы и данные.
Как защититься?
- Используйте подготовленные выражения (prepared statements): Это самый надёжный способ. Параметры передаются отдельно от SQL-кода, и внедрение становится невозможным.
- Экранируйте специальные символы: Если prepared statements недоступны, применяйте функции экранирования (например,
mysqli_real_escape_string). - Ограничивайте права пользователя БД: Не давайте приложению прав на чтение системных таблиц, если это не нужно.
- Отключайте вывод ошибок: Не показывайте пользователям детали ошибок SQL — это может помочь атакующему.
- Используйте WAF: Веб-application firewall может блокировать подозрительные запросы.
- Регулярно обновляйте СУБД: В MySQL 8.0.17 функции EXTRACTVALUE и UPDATEXML удалены, что снижает риск подобных атак.
Заключение
Строка ) AND EXTRACTVALUE(7289,CONCAT(0x7e,((SELECT (ELT(7289=7289,1)))),0x7e))-- - — это не случайный набор символов, а тщательно сконструированный эксплойт для SQL-инъекции. Понимание принципов его работы помогает разработчикам и специалистам по безопасности лучше защищать свои приложения. Никогда не доверяйте пользовательскому вводу и всегда используйте параметризованные запросы.
Комментарии
—Войдите, чтобы оставить комментарий