Введение

В запросе пользователя указана строка: %")) AND EXTRACTVALUE(6687,CONCAT(0x7e,((SELECT (ELT(6687=6687,1)))),0x7e))-- -. Это не случайный набор символов, а типичный пример error-based SQL-инъекции для СУБД MySQL. Такие строки часто встречаются в логах веб-серверов, когда злоумышленники пытаются проэксплуатировать уязвимость в параметрах приложения.

В этой статье мы разберём, что означает каждый элемент данной конструкции, как она работает и почему считается классическим приёмом атак на базы данных.

Что такое error-based SQL-инъекция?

SQL-инъекция — это способ внедрения вредоносного SQL-кода в запрос через пользовательский ввод. Error-based (основанная на ошибках) — разновидность, при которой атакующий заставляет СУБД вернуть сообщение об ошибке, содержащее полезные данные. Если приложение выводит такие ошибки на страницу, злоумышленник может читать информацию из базы: имена таблиц, логины, пароли и т.д.

В MySQL для этого часто используют функции EXTRACTVALUE и UPDATEXML. Они вызывают ошибку формата XML, если второй аргумент содержит недопустимые символы, и в тексте ошибки отображается переданное значение.

Разбор строки по частям

Рассмотрим фрагмент %")) AND EXTRACTVALUE(6687,CONCAT(0x7e,((SELECT (ELT(6687=6687,1)))),0x7e))-- - детально.

1. Префикс %"))

Знак % — это символ подстановки в LIKE-запросах. Далее идут закрывающая кавычка " и две закрывающие скобки )). Это попытка «закрыть» ранее открытые конструкции в исходном SQL-запросе, чтобы внедрить свой код. Количество скобок и кавычек подбирается под конкретный запрос.

2. AND EXTRACTVALUE(6687, ...)

Функция EXTRACTVALUE(XML_document, XPath_expression) извлекает значение из XML. Если второй аргумент не является корректным XPath-выражением, MySQL генерирует ошибку. Злоумышленник использует это для вывода данных: в тексте ошибки будет указано значение, которое он передал.

Число 6687 — это произвольный идентификатор (может быть любым). Он не несёт смысловой нагрузки, кроме как заполнить первый аргумент.

3. CONCAT(0x7e, ((SELECT (ELT(6687=6687,1)))), 0x7e)

CONCAT объединяет строки. 0x7e — шестнадцатеричное представление символа ~ (тильда). Тильда используется как разделитель, чтобы облегчить поиск выведенных данных в сообщении об ошибке.

Внутри CONCAT стоит подзапрос SELECT (ELT(6687=6687,1)). Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 6687=6687 — это логическое выражение, которое всегда истинно, то есть возвращает 1. Значит, ELT(1, 1) вернёт строку '1'. Это простейший пример. В реальной атаке вместо 1 мог бы стоять подзапрос, извлекающий данные (например, SELECT password FROM users LIMIT 1), но в данном случае используется заглушка для демонстрации.

4. Завершение -- -

Два дефиса и пробел — это комментарий в SQL. Всё, что идёт после, игнорируется. Это позволяет «отрезать» остаток оригинального запроса, чтобы он не вызвал синтаксическую ошибку.

Как это работает на практике

Предположим, исходный запрос выглядит так:

SELECT * FROM articles WHERE title LIKE '%ЗАПРОС%'

После подстановки вредоносной строки вместо ЗАПРОС получаем:

SELECT * FROM articles WHERE title LIKE '%%")) AND EXTRACTVALUE(6687,CONCAT(0x7e,((SELECT (ELT(6687=6687,1)))),0x7e))-- -%'

База данных выполнит EXTRACTVALUE с аргументом, содержащим тильды и результат подзапроса. Так как XPath-выражение ~1~ некорректно, MySQL выдаст ошибку вида:

XPATH syntax error: '~1~'

В этом сообщении атакующий увидит значение 1. Если вместо 1 подставить подзапрос к таблице пользователей, в ошибке отобразится, например, хеш пароля.

Почему это опасно?

Error-based инъекции позволяют злоумышленнику получать данные из базы посимвольно или целыми строками, не имея прямого доступа к СУБД. Если приложение показывает ошибки базы данных пользователю, это критическая уязвимость. Даже если ошибки скрыты, атакующий может использовать слепые методы, но error-based — самый быстрый и удобный способ.

Как защититься?

  • Используйте подготовленные выражения (prepared statements). Они разделяют код и данные, делая внедрение невозможным.
  • Экранируйте пользовательский ввод. Но это менее надёжно, чем параметризация.
  • Отключайте вывод ошибок СУБД на продакшене. Пользователь не должен видеть технические детали.
  • Применяйте WAF (Web Application Firewall). Он может блокировать подозрительные строки, содержащие EXTRACTVALUE и подобные функции.
  • Регулярно обновляйте СУБД и фреймворки. Устаревшие версии могут иметь дополнительные уязвимости.

Заключение

Строка %")) AND EXTRACTVALUE(6687,CONCAT(0x7e,((SELECT (ELT(6687=6687,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции для MySQL. Она демонстрирует, как через функцию EXTRACTVALUE и логические выражения можно заставить базу данных вывести произвольные данные в сообщении об ошибке. Понимание таких конструкций помогает разработчикам и специалистам по безопасности лучше защищать веб-приложения.

Если вы нашли подобную строку в логах — это признак попытки взлома. Следует немедленно проверить уязвимости и усилить защиту.

Источники