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

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

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

Давайте разберём эту строку на составляющие, чтобы понять логику атаки.

1. %' — закрытие исходного запроса

Символ % часто используется в SQL-запросах как шаблон для поиска (например, в LIKE '%...%'). Закрывающая кавычка ' пытается завершить строковый литерал в исходном запросе, чтобы далее внедрить собственный код. Если приложение не фильтрует ввод, это позволяет «вырваться» из контекста и добавить произвольные SQL-выражения.

2. OR EXTRACTVALUE(...) — вызов уязвимой функции

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

В нашем случае первый аргумент — 1855 (произвольное число, может быть любым), второй — CONCAT(0x7e,((SELECT (ELT(1855=1855,1)))),0x7e).

3. CONCAT(0x7e, ..., 0x7e) — формирование строки с тильдами

0x7e — это шестнадцатеричное представление символа ~ (тильда). Он используется как маркер, чтобы в сообщении об ошибке легко было найти внедрённые данные. Конструкция CONCAT('~', ..., '~') оборачивает результат подзапроса в тильды.

4. SELECT (ELT(1855=1855,1)) — проверка условия

ELT(N, str1, str2, ...) — функция MySQL, возвращающая N-ю строку из списка. Если N=1, возвращается первая строка, если N=2 — вторая и т.д. Если N меньше 1 или больше числа аргументов, возвращается NULL.

Выражение 1855=1855 всегда истинно, поэтому в MySQL оно приводится к числу 1. Таким образом, ELT(1, 1) вернёт строку '1'. Это простейший пример; в реальных атаках вместо 1855=1855 может стоять подзапрос, извлекающий данные (например, имя таблицы, версию СУБД и т.п.).

5. -- - — комментарий

Двойной дефис с пробелом (или -- -) в MySQL означает начало комментария до конца строки. Это позволяет «отрезать» оставшуюся часть оригинального SQL-запроса, чтобы синтаксис был корректным.

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

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

SELECT * FROM users WHERE name LIKE '%ЗАПРОС%';

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

SELECT * FROM users WHERE name LIKE '%%' OR EXTRACTVALUE(1855,CONCAT(0x7e,((SELECT (ELT(1855=1855,1)))),0x7e))-- -%';

MySQL выполнит EXTRACTVALUE с некорректным XPath (второй аргумент не является допустимым XPath-выражением), что вызовет ошибку вида:

ERROR 1105 (HY000): XPATH syntax error: '~1~'

В сообщении об ошибке мы видим ~1~ — это результат подзапроса, обёрнутый тильдами. Злоумышленник может заменить ELT(1855=1855,1) на подзапрос, возвращающий, например, имя текущей базы данных, версию MySQL или хеши паролей. Ошибка выведет эти данные прямо в ответе сервера.

Зачем это нужно атакующему?

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

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

  • Используйте параметризованные запросы (prepared statements). Это самый надёжный способ: данные никогда не интерпретируются как SQL-код.
  • Экранируйте специальные символы. Если параметризация невозможна, применяйте функции экранирования, предоставляемые драйвером БД (например, mysqli_real_escape_string в PHP).
  • Отключите вывод ошибок СУБД на продакшене. Сообщения об ошибках должны логироваться, а не показываться пользователю.
  • Ограничьте права пользователя БД. Веб-приложение должно работать с минимально необходимыми привилегиями.
  • Используйте WAF. Веб-приложения-экраны могут блокировать подозрительные конструкции, но не полагайтесь только на них.

Вывод

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

Источники