Введение
В логах веб-сервера, в поле ввода или в параметрах URL иногда можно встретить загадочную последовательность символов: ) AND EXTRACTVALUE(4679,CONCAT(0x7e,((SELECT (ELT(4679=4679,1)))),0x7e))-- -. Для неподготовленного пользователя это выглядит как случайный набор знаков, но на самом деле перед нами классический пример SQL-инъекции, нацеленной на извлечение данных из базы через сообщения об ошибках. В этой статье мы разберём, что означает каждый элемент запроса, как работает атака и как от неё защититься.
Что такое SQL-инъекция?
SQL-инъекция (SQL injection) — один из самых распространённых способов взлома веб-приложений. Злоумышленник вставляет в пользовательский ввод специально сконструированные фрагменты SQL-кода, которые затем выполняются на сервере баз данных. Цель может быть разной: обход аутентификации, кража конфиденциальной информации, удаление или изменение данных. В зависимости от метода получения результата выделяют несколько типов инъекций: union-based, boolean-based, time-based и error-based. Рассматриваемый запрос относится именно к последнему типу.
Разбор строки запроса
Давайте разложим выражение на составляющие:
)— закрывающая скобка. Она нужна, чтобы «закрыть» ранее открытую скобку в оригинальном SQL-запросе, который формирует уязвимое приложение. Без этого внедряемый код вызовет синтаксическую ошибку.AND EXTRACTVALUE(4679,CONCAT(0x7e,((SELECT (ELT(4679=4679,1)))),0x7e))— основная полезная нагрузка. ФункцияEXTRACTVALUE()в MySQL предназначена для извлечения значения из XML-документа по указанному XPath-выражению. Однако при передаче некорректного XPath она генерирует ошибку, в тексте которой может содержаться переданная строка.-- -— комментарий. В MySQL последовательность--(с последующим пробелом) означает начало комментария до конца строки. Это позволяет «отрезать» оставшуюся часть оригинального запроса, чтобы он не вызвал синтаксическую ошибку.
Функция EXTRACTVALUE и её роль
Функция EXTRACTVALUE(XML_document, XPath_expression) возвращает текст из XML-документа, соответствующий XPath-выражению. Если XPath-выражение синтаксически неверно, MySQL выдаёт ошибку вида: XPATH syntax error: '...'. Злоумышленники научились помещать в XPath результат подзапроса, чтобы этот результат попал в текст ошибки. Например, выражение CONCAT(0x7e, (SELECT ...), 0x7e) формирует строку, начиная и заканчивая символом тильды (~, код 0x7e). Тильда используется как маркер, чтобы легко найти извлечённые данные в сообщении об ошибке.
Подзапрос с ELT
Внутри CONCAT находится подзапрос (SELECT (ELT(4679=4679,1))). Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Если N=1, возвращается первый аргумент. Выражение 4679=4679 всегда истинно и в числовом контексте даёт 1. Таким образом, ELT(1,1) вернёт строку '1'. В данном примере это просто демонстрация: злоумышленник проверяет, работает ли инъекция. В реальной атаке вместо '1' мог бы быть, например, database(), user() или (SELECT password FROM users LIMIT 1).
Как происходит атака
Предположим, уязвимое приложение формирует запрос так:
SELECT * FROM products WHERE id = '$_GET[id]'
Если пользователь передаст в параметре id значение 1') AND EXTRACTVALUE(4679,CONCAT(0x7e,((SELECT (ELT(4679=4679,1)))),0x7e))-- -, то итоговый SQL-запрос примет вид:
SELECT * FROM products WHERE id = '1') AND EXTRACTVALUE(4679,CONCAT(0x7e,((SELECT (ELT(4679=4679,1)))),0x7e))-- -'
После закрытия скобки и кавычки внедрённый код выполнится. MySQL попытается вычислить EXTRACTVALUE с аргументом ~1~ (результат CONCAT). Поскольку ~1~ не является корректным XPath, возникнет ошибка, и в ответе сервера появится сообщение, содержащее ~1~. Атакующий, анализируя ответ, может подставлять вместо '1' другие выражения и постепенно извлекать данные из базы.
Чем опасна error-based инъекция
Этот метод позволяет получать информацию напрямую в тексте ошибок, что делает его очень удобным для злоумышленника. С его помощью можно узнать:
- имя текущей базы данных (
database()); - версию MySQL (
version()); - имя пользователя, от которого работает приложение (
user()); - список таблиц и столбцов через
information_schema; - конкретные данные, например логины и пароли.
Всё это может привести к полной компрометации базы данных.
Методы защиты
Чтобы предотвратить подобные атаки, необходимо следовать ряду правил:
- Использовать подготовленные выражения (prepared statements). Это самый надёжный способ. Параметры передаются отдельно от SQL-кода, и внедрение становится невозможным.
- Экранировать специальные символы. Если по каким-то причинам нельзя использовать подготовленные выражения, применяйте функции экранирования, например
mysqli_real_escape_string(). - Проверять типы данных. Если параметр должен быть числом, приводите его к целому типу.
- Ограничивать права пользователя БД. Приложение должно работать с минимально необходимыми привилегиями.
- Отключать вывод ошибок на продакшене. Сообщения об ошибках не должны попадать в ответ клиенту.
- Использовать WAF. Веб-application firewall может блокировать известные шаблоны атак.
Заключение
Строка ) AND EXTRACTVALUE(4679,CONCAT(0x7e,((SELECT (ELT(4679=4679,1)))),0x7e))-- - — это не случайный мусор, а целенаправленная попытка эксплуатации уязвимости SQL-инъекции. Понимание механизмов таких атак помогает разработчикам и администраторам своевременно закрывать дыры в безопасности. Если вы обнаружили подобные записи в логах, это сигнал о необходимости проверить код приложения на наличие уязвимостей и усилить защиту.
Комментарии
—Войдите, чтобы оставить комментарий