Что это за строка?

Строка '))) AND EXTRACTVALUE(5410,CONCAT(0x7e,((SELECT (ELT(5410=5410,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции (инъекции на основе ошибок) для СУБД MySQL. Такие конструкции используют для извлечения данных из базы через сообщения об ошибках. Подобные payload'ы часто встречаются в отчётах сканеров уязвимостей и в задачах по информационной безопасности.

В отличие от UNION-based или blind-инъекций, error-based метод заставляет сервер вернуть результат подзапроса прямо в тексте ошибки. Это делает его очень удобным для ручного анализа, когда нужно быстро получить имя пользователя, версию СУБД или другую информацию.

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

1. Начало: ')))

Три закрывающие скобки и апостроф. Это попытка «закрыть» оригинальный SQL-запрос, в который внедряется payload. Разработчик мог использовать конструкцию вида WHERE id = (('...')), и инъекция ломает синтаксис, добавляя свои условия.

2. AND EXTRACTVALUE(...)

EXTRACTVALUE — функция MySQL (до версии 8.0.17), которая извлекает значение из XML-строки по XPath-выражению. Если XPath содержит недопустимые символы, MySQL выбрасывает ошибку и включает в неё переданный фрагмент. Это и есть канал утечки данных.

3. 5410 и CONCAT(0x7e, ..., 0x7e)

Первый аргумент 5410 — произвольное число (может быть любым, часто используется случайное). Второй аргумент — строка, которую мы хотим «протащить» в ошибку. 0x7e — это шестнадцатеричный код символа ~ (тильда). Тильда используется как маркер, чтобы легко найти выводимые данные в тексте ошибки.

4. ((SELECT (ELT(5410=5410,1))))

Здесь мы видим подзапрос. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае 5410=5410 — это всегда истина (1), поэтому ELT(1, 1) вернёт 1. Это простейший тест: если инъекция работает, в ошибке появится ~1~. На практике вместо 1 подставляют вызовы вроде version(), user(), database() или подзапросы к information_schema.

5. Завершение: -- -

Комментарий, который «съедает» остаток оригинального запроса. Пробел после -- обязателен в MySQL, иначе комментарий не сработает. Иногда вместо -- - используют # или /* */.

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

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

SELECT * FROM users WHERE id = ('$input')

Подставляем payload и получаем:

SELECT * FROM users WHERE id = ('1'))) AND EXTRACTVALUE(5410,CONCAT(0x7e,((SELECT (ELT(5410=5410,1)))),0x7e))-- -')

СУБД выполнит EXTRACTVALUE и вернёт ошибку вида:

XPATH syntax error: '~1~'

Если вместо 1 подставить version(), в ошибке появится версия MySQL. Такой метод позволяет извлекать данные посимвольно или целыми строками, если позволяет длина сообщения об ошибке.

Зачем это нужно знать?

Понимание error-based SQL-инъекций важно как для специалистов по безопасности, так и для разработчиков. OWASP регулярно включает SQL-инъекции в топ-10 критических уязвимостей. Знание конкретных payload'ов помогает:

  • правильно настраивать WAF и фильтры ввода;
  • проводить пентесты и аудиты кода;
  • писать безопасные запросы с параметризацией.

Стоит помнить, что EXTRACTVALUE удалена в MySQL 8.0.17 и заменена на UPDATEXML и другие функции. Однако на старых версиях (5.7 и ниже) она по-прежнему работает и активно используется в эксплойтах.

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

Главная мера — использовать подготовленные выражения (prepared statements) с параметрами. Никогда не конкатенируйте пользовательский ввод в SQL-запрос. Дополнительно:

  • ограничьте права пользователя БД (не давайте доступ к information_schema без необходимости);
  • включите логирование ошибок, но не показывайте их пользователю;
  • используйте ORM с параметризацией.

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

Источники