Встречая в логах веб-сервера или в поле ввода подобную строку: )))) AND EXTRACTVALUE(2219,CONCAT(0x7e,((SELECT (ELT(2219=2219,1)))),0x7e))-- -, многие задаются вопросом: что это и какова её цель? Это классический пример SQL-инъекции, нацеленной на извлечение данных из базы через сообщения об ошибках. В данной статье мы подробно разберём каждую часть этого запроса, объясним, как работает атака, и расскажем, как защититься.
Что такое SQL-инъекция?
SQL-инъекция (SQL injection) — один из самых распространённых способов взлома веб-приложений. Злоумышленник вставляет в пользовательский ввод специальные конструкции, которые интерпретируются базой данных как исполняемый код. Это позволяет читать, изменять или удалять данные, к которым у атакующего не должно быть доступа.
Существует несколько типов SQL-инъекций: union-based, boolean-based, time-based и error-based. Рассматриваемая строка относится именно к error-based — методу, при котором результат извлекается через текст ошибки, возвращаемый СУБД.
Разбор строки по частям
Давайте разберём запрос на составляющие, чтобы понять его логику.
1. `))))` — закрытие скобок
Начинается строка с нескольких закрывающих круглых скобок. Это не случайность: атакующий предполагает, что исходный SQL-запрос содержит открытые скобки (например, в условиях WHERE (id = ...)). Закрывая их, он пытается «выровнять» синтаксис и внедрить свою конструкцию без ошибок парсинга.
2. `AND` — логическое продолжение
Ключевое слово AND говорит о том, что злоумышленник дописывает условие к существующему WHERE. Это позволяет внедрить произвольное выражение, которое будет вычислено сервером базы данных.
3. `EXTRACTVALUE(2219, CONCAT(...))`
EXTRACTVALUE — функция MySQL, предназначенная для извлечения значения из XML-строки по указанному XPath-выражению. Однако в контексте инъекции она используется иначе. Если второй аргумент функции содержит недопустимый XPath (например, начинается с символа ~), MySQL генерирует ошибку, в тексте которой отображается переданное значение. Это и есть механизм error-based инъекции: атакующий подставляет в XPath результат подзапроса, а затем читает его из сообщения об ошибке.
4. `CONCAT(0x7e, ..., 0x7e)`
Функция CONCAT объединяет строки. Здесь она оборачивает извлекаемые данные символами 0x7e — это шестнадцатеричное представление тильды ~. Тильда используется как маркер, чтобы в длинном тексте ошибки легко найти начало и конец полезной нагрузки.
5. `(SELECT (ELT(2219=2219,1)))`
Внутренний подзапрос содержит функцию ELT. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Выражение 2219=2219 всегда истинно, поэтому ELT вернёт первый элемент — 1. В реальной атаке вместо этой заглушки подставляется подзапрос, извлекающий данные (например, SELECT version() или SELECT password FROM users LIMIT 1).
6. `-- -` — комментарий
Два дефиса с пробелом (или без) в MySQL означают начало комментария до конца строки. Это необходимо, чтобы «отрезать» оставшуюся часть оригинального SQL-запроса, которая могла бы вызвать синтаксическую ошибку. Пробел после -- обязателен в некоторых версиях MySQL.
Как работает атака целиком
Предположим, уязвимый запрос выглядит так:
SELECT * FROM products WHERE id = '$input';
Если пользователь передаст 1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))-- -, то после подстановки получится:
SELECT * FROM products WHERE id = '1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))-- -';
MySQL попытается выполнить EXTRACTVALUE с XPath, начинающимся с тильды. Это вызовет ошибку вида:
XPATH syntax error: '~5.7.33~'
В тексте ошибки злоумышленник увидит версию СУБД. Аналогично можно извлечь имена таблиц, колонок, хеши паролей и другие конфиденциальные данные.
Почему используется именно EXTRACTVALUE?
Функция EXTRACTVALUE доступна в MySQL и MariaDB. В отличие от UPDATEXML, она часто не отключается в конфигурациях по умолчанию. Кроме того, она позволяет обойти некоторые фильтры, так как не содержит ключевых слов вроде UNION или SELECT в явном виде (хотя подзапрос всё же присутствует).
Как защититься от таких инъекций
Главное правило — никогда не конкатенировать пользовательский ввод в SQL-запросы. Используйте подготовленные выражения (prepared statements) с параметризацией. В PHP это PDO или mysqli с bind_param; в Python — cursor.execute с плейсхолдерами; в Java — PreparedStatement.
Дополнительные меры:
- Валидация и фильтрация входных данных по белому списку.
- Ограничение прав пользователя БД: приложению не нужны права
FILEилиEXECUTE. - Отключение вывода подробных ошибок СУБД в продакшене.
- Использование WAF (Web Application Firewall) для блокировки подозрительных запросов.
- Регулярное обновление СУБД и фреймворков.
Что делать, если вы нашли такую строку в логах
Если вы обнаружили подобный запрос в логах, это может означать, что ваш сайт пытались взломать. Не паникуйте, но проверьте:
- Уязвим ли ваш код к SQL-инъекциям (проведите аудит).
- Не произошло ли утечки данных (проверьте логи доступа к БД).
- Обновите ПО и настройте WAF.
Помните: даже если атака не удалась, сам факт её наличия — сигнал о необходимости усилить безопасность.
Заключение
Строка )))) AND EXTRACTVALUE(2219,CONCAT(0x7e,((SELECT (ELT(2219=2219,1)))),0x7e))-- - — это не случайный набор символов, а тщательно сконструированная полезная нагрузка для error-based SQL-инъекции в MySQL. Понимание её структуры помогает разработчикам и специалистам по безопасности лучше защищать свои приложения. Используйте параметризованные запросы, ограничивайте права БД и следите за логами — это базовые, но эффективные меры.
Комментарии
—Войдите, чтобы оставить комментарий