Введение
Встречая в логах веб-сервера или в поле ввода подобную строку: ) AND EXTRACTVALUE(8894,CONCAT(0x7e,((SELECT (ELT(8894=8894,1)))),0x7e))-- -, многие задаются вопросом: что это и какова её цель? Это классический пример SQL-инъекции, нацеленной на извлечение данных из базы данных через генерацию ошибок. В данной статье мы подробно разберём каждую часть этой конструкции, объясним, как она работает, и расскажем, как защитить свой сайт от подобных атак.
Что такое SQL-инъекция?
SQL-инъекция (SQL injection) — это один из самых распространённых способов взлома веб-приложений. Злоумышленник внедряет вредоносный SQL-код в запрос, который приложение отправляет базе данных. Если приложение не проверяет входные данные должным образом, этот код выполняется, что может привести к утечке конфиденциальной информации, изменению или удалению данных, а в некоторых случаях — к полному контролю над сервером.
Существует несколько типов SQL-инъекций: основанные на ошибках (error-based), на времени (time-based), на логических выражениях (boolean-based) и UNION-инъекции. Конструкция, которую мы рассматриваем, относится к error-based инъекциям, так как использует функцию, вызывающую ошибку с внедрёнными данными.
Разбор конструкции AND EXTRACTVALUE(8894,CONCAT(0x7e,((SELECT (ELT(8894=8894,1)))),0x7e))-- -
Давайте разберём эту строку по частям.
1. AND
Логический оператор AND используется для добавления условия к существующему запросу. Злоумышленник пытается сделать так, чтобы внедрённое выражение выполнилось, только если исходное условие истинно (или ложно, в зависимости от логики).
2. EXTRACTVALUE(8894, CONCAT(...))
EXTRACTVALUE — это функция MySQL (и MariaDB), которая извлекает значение из XML-строки. Она принимает два аргумента: XML-документ и XPath-выражение. Если XPath-выражение некорректно или возвращает несколько узлов, функция генерирует ошибку, в тексте которой содержится результат вычисления XPath. Именно это и используется для извлечения данных: злоумышленник подставляет в XPath результат подзапроса, и если тот содержит недопустимые символы, ошибка выводит эти символы.
3. CONCAT(0x7e, ((SELECT (ELT(8894=8894,1)))), 0x7e)
CONCAT объединяет строки. Здесь он склеивает тильду (0x7e — шестнадцатеричный код символа ~), результат подзапроса и ещё одну тильду. Тильда используется как разделитель, чтобы облегчить парсинг вывода ошибки.
4. (SELECT (ELT(8894=8894,1)))
ELT — функция MySQL, возвращающая N-й элемент из списка строк. ELT(N, str1, str2, ...) возвращает strN. В данном случае ELT(8894=8894,1) — первый аргумент это логическое выражение 8894=8894, которое всегда истинно (1). Значит, ELT(1,1) вернёт строку '1'. Это простейшая проверка работоспособности инъекции. В реальных атаках вместо 1 может быть подзапрос, извлекающий имена таблиц, пароли и т.д.
5. -- -
Два дефиса и пробел (или дефис) обозначают комментарий в SQL. Всё, что идёт после -- , игнорируется базой данных. Это нужно, чтобы обрезать оставшуюся часть оригинального запроса, которая могла бы вызвать синтаксическую ошибку.
Как работает атака на практике
Предположим, на сайте есть страница с параметром id, и запрос выглядит так:
SELECT * FROM products WHERE id = '$id';
Злоумышленник передаёт в $id значение 1' AND EXTRACTVALUE(8894,CONCAT(0x7e,((SELECT (ELT(8894=8894,1)))),0x7e))-- -. После подстановки запрос становится:
SELECT * FROM products WHERE id = '1' AND EXTRACTVALUE(8894,CONCAT(0x7e,((SELECT (ELT(8894=8894,1)))),0x7e))-- -';
База данных выполняет EXTRACTVALUE. Поскольку второй аргумент содержит символ ~, который не является допустимым XPath, MySQL выдаёт ошибку вида:
XPATH syntax error: '~1~'
В тексте ошибки появляется ~1~. Это подтверждает, что инъекция работает. Далее злоумышленник может заменить ELT(8894=8894,1) на подзапрос, например, (SELECT password FROM users LIMIT 1), и извлекать данные посимвольно или целыми строками, если позволяет длина вывода ошибки.
Какие функции MySQL задействованы?
- EXTRACTVALUE — извлекает значение из XML; при ошибке выводит результат в сообщении.
- CONCAT — объединяет строки, добавляя маркеры (тильды) для облегчения парсинга.
- ELT — возвращает элемент по индексу; используется для проверки или подстановки данных.
- 0x7e — шестнадцатеричное представление символа
~, который часто используется как разделитель, так как редко встречается в обычных данных.
Стоит отметить, что функция EXTRACTVALUE устарела начиная с MySQL 5.6.6 и может быть удалена в будущих версиях. Однако она всё ещё поддерживается во многих установках, что делает её популярной среди злоумышленников.
Чем опасна такая инъекция?
Успешная error-based инъекция позволяет злоумышленнику:
- Получить доступ к структуре базы данных (имена таблиц, столбцов).
- Извлечь конфиденциальные данные: логины, пароли (в виде хешей), персональные данные пользователей.
- В некоторых случаях — выполнить произвольные SQL-запросы, включая изменение или удаление данных.
Даже если приложение не выводит ошибки базы данных напрямую, злоумышленник может использовать слепые методы (boolean-based или time-based), но в данном случае конструкция явно рассчитана на вывод ошибок.
Как защититься от SQL-инъекций?
Основная причина успешных инъекций — недостаточная фильтрация входных данных и конкатенация их в SQL-запросы. Вот ключевые меры защиты:
- Используйте подготовленные запросы (prepared statements) с параметризацией. Это самый надёжный способ: данные передаются отдельно от SQL-кода, и база данных не интерпретирует их как часть запроса.
- Применяйте хранимые процедуры. Они также позволяют отделить код от данных, если правильно используются.
- Экранируйте специальные символы. Например, с помощью функции
mysqli_real_escape_stringв PHP, но это менее надёжно, чем подготовленные запросы. - Ограничивайте права пользователя базы данных. Не давайте приложению права на удаление таблиц или доступ к системным таблицам, если это не необходимо.
- Отключайте вывод ошибок базы данных в production. Сообщения об ошибках должны логироваться, но не показываться пользователю.
- Регулярно обновляйте СУБД и используйте современные версии. В новых версиях MySQL функция
EXTRACTVALUEможет быть удалена, что снизит риск. - Проводите аудит кода и используйте сканеры уязвимостей.
Также рекомендуется использовать веб-application firewall (WAF), который может блокировать подозрительные запросы, содержащие характерные паттерны вроде EXTRACTVALUE и CONCAT(0x7e.
Заключение
Строка AND EXTRACTVALUE(8894,CONCAT(0x7e,((SELECT (ELT(8894=8894,1)))),0x7e))-- - — это не случайный набор символов, а тщательно сконструированная SQL-инъекция, использующая особенности функций MySQL для извлечения данных через сообщения об ошибках. Понимание механизма таких атак помогает разработчикам и администраторам своевременно принимать меры защиты. Никогда не доверяйте пользовательскому вводу и всегда используйте параметризованные запросы — это золотое правило веб-безопасности.
Комментарии
—Войдите, чтобы оставить комментарий