Введение
Встречая в логах или в поле ввода подобную строку: AND EXTRACTVALUE(6196,CONCAT(0x7e,((SELECT (ELT(6196=6196,1)))),0x7e))-- -, многие задаются вопросом: что это и какова её цель? Это классический пример SQL-инъекции, нацеленной на извлечение данных из базы через вывод сообщения об ошибке. В данной статье мы подробно разберём, как работает эта атака, какие функции MySQL задействованы и как защититься от подобных угроз.
Что такое SQL-инъекция?
SQL-инъекция (SQL injection) — один из самых распространённых способов взлома веб-приложений. Злоумышленник внедряет вредоносный SQL-код в поля ввода, URL-параметры или другие данные, передаваемые на сервер. Если приложение не фильтрует входные данные, база данных выполняет этот код, что может привести к утечке конфиденциальной информации, изменению или удалению данных, а в некоторых случаях — к полному захвату сервера.
Существует несколько типов SQL-инъекций: классические (union-based), слепые (blind), временные (time-based) и основанные на ошибках (error-based). Рассматриваемая строка относится именно к последнему типу.
Разбор строки: EXTRACTVALUE и CONCAT
Давайте детально разберём каждый элемент запроса:
- EXTRACTVALUE(6196, ...) — функция MySQL, предназначенная для извлечения значения из XML-документа. Она принимает два аргумента: XML-строку и XPath-выражение. Если второй аргумент содержит недопустимый XPath, MySQL генерирует ошибку, в тексте которой отображается переданное значение. Это и используется для извлечения данных.
- CONCAT(0x7e, ..., 0x7e) — функция конкатенации строк. Здесь 0x7e — это шестнадцатеричное представление символа «~» (тильда). Тильды добавляются как маркеры, чтобы облегчить поиск выведенных данных в сообщении об ошибке.
- (SELECT (ELT(6196=6196,1))) — подзапрос, который возвращает результат функции ELT. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае условие 6196=6196 всегда истинно (возвращает 1), поэтому ELT(1,1) вернёт «1». Это простейший пример; на практике вместо «1» может быть внедрён подзапрос, извлекающий реальные данные (например, версию СУБД, имена таблиц, пароли).
- -- - — комментарий в SQL. Всё, что идёт после него, игнорируется базой данных. Это позволяет обрезать исходный запрос и избежать синтаксических ошибок.
Таким образом, вся конструкция заставляет MySQL выполнить функцию EXTRACTVALUE с заведомо некорректным XPath, что приводит к ошибке, в тексте которой будет содержаться результат подзапроса, обрамлённый тильдами. Злоумышленник может прочитать это сообщение и получить нужные данные.
Как это работает на практике
Предположим, на сайте есть страница с параметром id=1, и запрос к базе формируется так:
SELECT * FROM products WHERE id = 1;
Злоумышленник подставляет вместо 1 следующую строку:
1 AND EXTRACTVALUE(6196,CONCAT(0x7e,((SELECT (ELT(6196=6196,1)))),0x7e))-- -
Итоговый запрос принимает вид:
SELECT * FROM products WHERE id = 1 AND EXTRACTVALUE(6196,CONCAT(0x7e,((SELECT (ELT(6196=6196,1)))),0x7e))-- -;
MySQL выполняет запрос, доходит до функции EXTRACTVALUE, пытается интерпретировать строку ~1~ как XPath и терпит неудачу. В ответе сервера появляется сообщение об ошибке вида:
XPATH syntax error: '~1~'
Злоумышленник видит этот текст и понимает, что инъекция сработала. Далее он может заменить ELT(6196=6196,1) на подзапрос, например, (SELECT version()), и получить версию MySQL. Аналогично можно извлекать имена таблиц, столбцов и даже хеши паролей.
Почему используются именно EXTRACTVALUE и CONCAT?
Функция EXTRACTVALUE часто применяется в error-based инъекциях, потому что она гарантированно вызывает ошибку при некорректном XPath. Аналогичными свойствами обладают функции UPDATEXML и EXP (в старых версиях MySQL). CONCAT с символами 0x7e помогает отделить выводимые данные от остального текста ошибки, делая их легко читаемыми.
Стоит отметить, что начиная с MySQL 5.7 функция EXTRACTVALUE была помечена как устаревшая, а в MySQL 8.0 удалена. Однако многие веб-приложения до сих пор работают на старых версиях, поэтому атака остаётся актуальной.
Как защититься от SQL-инъекций
Основной способ защиты — использование подготовленных выражений (prepared statements) с параметризацией запросов. Это полностью исключает возможность внедрения SQL-кода, так как данные передаются отдельно от самого запроса. Если по каким-то причинам это невозможно, следует применять:
- Экранирование всех входных данных с помощью функций типа
mysqli_real_escape_string. - Валидацию и фильтрацию входных параметров (например, приведение к целочисленному типу).
- Использование ORM (Object-Relational Mapping), которые автоматически параметризуют запросы.
- Ограничение прав пользователя базы данных: приложение должно работать с минимально необходимыми привилегиями.
- Регулярное обновление СУБД и веб-фреймворков.
Также рекомендуется настроить логирование подозрительных запросов и использовать WAF (Web Application Firewall), который может блокировать попытки SQL-инъекций на лету.
Заключение
Строка ' AND EXTRACTVALUE(6196,CONCAT(0x7e,((SELECT (ELT(6196=6196,1)))),0x7e))-- - — это не случайный набор символов, а тщательно сконструированная SQL-инъекция, использующая особенности функций MySQL для извлечения данных через сообщения об ошибках. Понимание механизмов таких атак помогает разработчикам и администраторам своевременно выявлять уязвимости и защищать свои системы. Если вы обнаружили подобные строки в логах, это серьёзный повод проверить безопасность вашего веб-приложения.
Комментарии
—Войдите, чтобы оставить комментарий