Что это за строка?
Строка %'))) AND EXTRACTVALUE(3720,CONCAT(0x7e,((SELECT (ELT(3720=3720,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции для СУБД MySQL. Она предназначена для извлечения данных из базы через вывод сообщения об ошибке. Подобные конструкции часто встречаются в отчётах пентестеров и в базах уязвимостей (например, в SQLMap).
Если коротко: злоумышленник внедряет в уязвимый параметр запроса код, который заставляет MySQL выполнить функцию EXTRACTVALUE с заведомо некорректным XPath-выражением. В результате сервер возвращает ошибку, содержащую результат подзапроса. Так можно узнать версию БД, имена таблиц, логины и пароли.
Разбор по частям
Давайте разберём каждый элемент конструкции.
Начало: %')))
Символ % часто используется как подстановочный знак в LIKE-запросах. Далее идут закрывающая кавычка ' и несколько закрывающих скобок ))). Это попытка «закрыть» оригинальный SQL-запрос, чтобы внедрить свой код. Количество скобок подбирается экспериментально в зависимости от структуры уязвимого запроса.
Функция EXTRACTVALUE(3720, ...)
EXTRACTVALUE — это встроенная функция MySQL (до версии 8.0), которая извлекает значение из XML-строки по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_фрагмент, XPath_выражение). Если XPath-выражение синтаксически некорректно, MySQL генерирует ошибку XPATH syntax error и включает в текст ошибки переданное XPath-выражение. Это и есть основа эксплуатации.
Первое число 3720 здесь — произвольное число, которое не влияет на работу, но часто используется для уникализации запроса или как часть условия.
CONCAT(0x7e, ((SELECT (ELT(3720=3720,1)))), 0x7e)
Функция CONCAT объединяет строки. 0x7e — это шестнадцатеричное представление символа ~ (тильда). Тильда используется как разделитель, чтобы облегчить извлечение данных из сообщения об ошибке.
Внутри CONCAT находится подзапрос: SELECT (ELT(3720=3720,1)). Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 3720=3720 — это всегда истинное условие, которое возвращает 1 (в MySQL true = 1). Таким образом, ELT(1, 1) вернёт строку '1'. В реальной атаке вместо 1 подставляется результат другого подзапроса, например, SELECT password FROM users LIMIT 1.
Итог: CONCAT формирует строку вида ~1~, которая затем передаётся как XPath-выражение в EXTRACTVALUE. Поскольку ~1~ не является корректным XPath, MySQL выбрасывает ошибку, включающую эту строку.
Комментарий -- -
Два дефиса и пробел (или дефис) — это комментарий в SQL. Он «отрезает» оставшуюся часть оригинального запроса, чтобы синтаксис был корректным.
Как это работает на практике
Предположим, есть уязвимый параметр id в запросе:
SELECT * FROM articles WHERE id = '%'
Злоумышленник подставляет нашу строку, и запрос превращается в:
SELECT * FROM articles WHERE id = '%'))) AND EXTRACTVALUE(3720,CONCAT(0x7e,((SELECT (ELT(3720=3720,1)))),0x7e))-- -'
MySQL выполняет EXTRACTVALUE, получает ошибку и возвращает её клиенту. В тексте ошибки будет что-то вроде:
XPATH syntax error: '~1~'
Если вместо 1 подставить, например, (SELECT version()), то в ошибке появится версия MySQL. Так пошагово извлекаются любые данные.
Зачем нужна такая сложность?
Почему бы просто не использовать UNION SELECT? Дело в том, что не всегда количество столбцов в оригинальном запросе совпадает с количеством в внедряемом, или приложение не выводит результаты запроса на страницу. Error-based инъекция позволяет получить данные даже там, где нет прямого вывода. EXTRACTVALUE — один из самых надёжных способов вызвать ошибку с контролируемым содержимым.
Актуальность и защита
Начиная с MySQL 8.0.17 функция EXTRACTVALUE была удалена (deprecated в 5.7). Однако многие системы до сих пор работают на старых версиях, поэтому угроза сохраняется. Кроме того, существуют аналоги: UPDATEXML, GTID_SUBSET и другие.
Чтобы защититься от подобных атак, необходимо:
- Использовать параметризованные запросы (prepared statements) — это самый надёжный способ.
- Применять ORM с автоматическим экранированием.
- Валидировать и фильтровать все входные данные, особенно те, что попадают в SQL.
- Регулярно обновлять СУБД и фреймворки.
- Настроить WAF для блокировки подозрительных конструкций.
Если вы обнаружили такую строку в логах своего сайта — это признак попытки взлома. Срочно проверьте код на уязвимости и закройте доступ к базе.
Заключение
Конструкция %'))) AND EXTRACTVALUE(3720,CONCAT(0x7e,((SELECT (ELT(3720=3720,1)))),0x7e))-- - — это не случайный набор символов, а тщательно составленный эксплойт для error-based SQL-инъекции в MySQL. Понимание принципов его работы помогает разработчикам и специалистам по безопасности лучше защищать свои приложения.
Комментарии
—Войдите, чтобы оставить комментарий