Введение
Встречая в логах или в поле ввода подобную строку: %')) AND EXTRACTVALUE(4930,CONCAT(0x7e,((SELECT (ELT(4930=4930,1)))),0x7e))-- -, многие задаются вопросом: что это и какова её цель? Это классический пример SQL-инъекции, нацеленной на извлечение данных из базы данных через ошибки. В данной статье мы подробно разберём, как работает этот запрос, какие функции MySQL задействованы и как защититься от подобных атак.
Что такое SQL-инъекция?
SQL-инъекция (SQL injection) — это один из самых распространённых способов взлома веб-приложений, при котором злоумышленник внедряет вредоносный SQL-код в запрос к базе данных. Это становится возможным, если приложение недостаточно фильтрует пользовательский ввод. Цель инъекции — обойти аутентификацию, украсть, изменить или удалить данные.
Существует несколько типов SQL-инъекций: UNION-based, error-based, blind, time-based и другие. Рассматриваемый запрос относится к error-based инъекциям, где злоумышленник заставляет базу данных вернуть данные в сообщении об ошибке.
Разбор запроса по частям
Давайте разберём строку %')) AND EXTRACTVALUE(4930,CONCAT(0x7e,((SELECT (ELT(4930=4930,1)))),0x7e))-- - поэтапно.
1. Начало: %'))
Символы %' и )) часто используются для закрытия ранее открытых кавычек и скобок в уязвимом запросе. Например, если оригинальный запрос выглядит как SELECT * FROM users WHERE name = '%...%', то вставка %')) может закрыть строку и дополнительную скобку, позволяя внедрить свой код.
2. AND EXTRACTVALUE(4930, CONCAT(...))
Функция EXTRACTVALUE() в MySQL предназначена для извлечения значения из XML-документа по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(xml_frag, xpath_expr). Однако при неправильном XPath-выражении она генерирует ошибку, которая может содержать переданные данные. Это и используется в error-based инъекциях.
Первый аргумент — 4930 — это произвольное число, которое не является корректным XML. Второй аргумент — CONCAT(...) — формирует строку, которая будет частью сообщения об ошибке.
3. CONCAT(0x7e, ((SELECT (ELT(4930=4930,1)))), 0x7e)
Функция CONCAT() объединяет строки. Здесь 0x7e — это шестнадцатеричное представление символа ~ (тильда). Тильда используется как маркер, чтобы легко найти извлечённые данные в сообщении об ошибке.
Внутри CONCAT находится подзапрос (SELECT (ELT(4930=4930,1))). Функция ELT() возвращает N-й элемент из списка. В данном случае ELT(4930=4930,1) — условие 4930=4930 всегда истинно, что даёт 1. То есть подзапрос возвращает 1. Это простейший пример; в реальной атаке вместо 1 могло бы быть имя пользователя, пароль или другая конфиденциальная информация, полученная из базы.
4. Завершение: -- -
Двойной дефис с пробелом -- - — это комментарий в SQL, который отсекает оставшуюся часть оригинального запроса, чтобы не вызвать синтаксическую ошибку.
Как это работает целиком
Когда уязвимое приложение подставляет эту строку в SQL-запрос, база данных выполняет:
SELECT ... WHERE ... '%')) AND EXTRACTVALUE(4930,CONCAT(0x7e,((SELECT (ELT(4930=4930,1)))),0x7e))-- - ...
Функция EXTRACTVALUE пытается обработать XPath, начинающийся с ~1~, что не является корректным XPath. MySQL возвращает ошибку вида: XPATH syntax error: '~1~'. В этом сообщении злоумышленник видит результат выполнения подзапроса — в данном случае 1. Если бы вместо 1 был, например, database(), то в ошибке отобразилось бы имя текущей базы данных.
Зачем это нужно злоумышленнику?
Error-based инъекции позволяют извлекать данные посимвольно или целыми строками, если приложение выводит сообщения об ошибках базы данных. Это один из самых быстрых способов получить информацию о структуре БД, учётных записях и других секретах.
Как защититься?
- Используйте подготовленные выражения (prepared statements) с параметризацией. Это самый надёжный способ, так как данные не интерпретируются как SQL-код.
- Экранируйте пользовательский ввод с помощью функций вроде
mysqli_real_escape_string. - Ограничьте права пользователя БД: не давайте приложению прав на чтение системных таблиц.
- Отключите вывод ошибок БД на продакшене, чтобы злоумышленник не мог использовать error-based инъекции.
- Используйте WAF (Web Application Firewall) для фильтрации подозрительных запросов.
Пример безопасного кода на PHP
Вместо уязвимого кода:
$query = "SELECT * FROM users WHERE name = '" . $_GET['name'] . "'";
Используйте подготовленные выражения:
$stmt = $pdo->prepare('SELECT * FROM users WHERE name = :name');
$stmt->execute(['name' => $_GET['name']]);
Заключение
Запрос %')) AND EXTRACTVALUE(4930,CONCAT(0x7e,((SELECT (ELT(4930=4930,1)))),0x7e))-- - — это типичный пример error-based SQL-инъекции, использующей особенности функций MySQL EXTRACTVALUE, CONCAT и ELT. Понимание механизмов таких атак помогает разработчикам создавать более безопасные приложения. Всегда проверяйте и фильтруйте пользовательский ввод, используйте параметризованные запросы и регулярно проводите аудит безопасности.
Комментарии
—Войдите, чтобы оставить комментарий