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

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

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

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

Разбор строки инъекции

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

  • OR — логический оператор, который добавляется к оригинальному условию. Если исходный запрос был SELECT ... WHERE id = '$id', то после подстановки получается WHERE id = '' OR EXTRACTVALUE(...). Это заставляет базу выполнить нашу функцию.
  • EXTRACTVALUE(8503, CONCAT(0x7e, ((SELECT (ELT(8503=8503,1)))), 0x7e)) — вызов функции EXTRACTVALUE с двумя аргументами. Первый аргумент (8503) — произвольное число, второй — XML-строка, сформированная через CONCAT.
  • CONCAT(0x7e, ((SELECT (ELT(8503=8503,1)))), 0x7e) — объединяет символ ~ (0x7e), результат подзапроса и снова ~. Символ ~ используется как маркер, чтобы в сообщении об ошибке было легко найти внедрённые данные.
  • (SELECT (ELT(8503=8503,1))) — подзапрос, возвращающий значение. ELT(N, str1, str2, ...) возвращает строку с номером N. Здесь условие 8503=8503 всегда истинно, поэтому ELT(1,1) вернёт 1. В реальной атаке вместо 1 подставляют подзапрос, извлекающий данные, например (SELECT password FROM users LIMIT 1).
  • -- - — комментарий, который отсекает оставшуюся часть оригинального SQL-запроса, чтобы не возникло синтаксической ошибки.

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

Когда MySQL выполняет EXTRACTVALUE(8503, '~1~'), функция пытается разобрать строку как XML. Поскольку ~1~ не является корректным XML-документом, СУБД генерирует ошибку вида:

XPATH syntax error: '~1~'

В этом сообщении содержится результат подзапроса. Атакующий, получая такие ошибки в ответе сервера, может посимвольно извлекать данные из базы. Например, подставляя вместо 1 подзапрос (SELECT table_name FROM information_schema.tables LIMIT 1), он получит имя первой таблицы в ошибке.

Зачем нужны 0x7e и ELT

0x7e — это шестнадцатеричное представление символа ~ (тильда). Он используется как разделитель, чтобы в сообщении об ошибке было легко отделить внедрённые данные от остального текста. ELT — функция, возвращающая N-ю строку из списка. В простейшем случае ELT(8503=8503,1) возвращает 1, так как условие истинно. Это демонстрационный пример; в реальной атаке вместо 1 может быть любой подзапрос.

Последствия успешной инъекции

Если злоумышленнику удаётся эксплуатировать такую уязвимость, он может:

  • получить доступ к конфиденциальным данным (пароли, персональные данные пользователей, платёжная информация);
  • изменить или удалить данные в базе;
  • выполнить административные операции, если у учётной записи базы данных достаточно прав;
  • получить полный контроль над сервером в некоторых конфигурациях.

Как защититься от error-based SQL-инъекций

Основной метод защиты — использование параметризованных запросов (prepared statements). Они гарантируют, что пользовательский ввод никогда не будет интерпретирован как SQL-код. Дополнительные меры:

  1. Экранирование специальных символов — если по каким-то причинам нельзя использовать prepared statements, применяйте функции экранирования, предоставляемые драйвером базы данных.
  2. Ограничение прав пользователя БД — учётная запись, от имени которой работает веб-приложение, должна иметь минимально необходимые привилегии.
  3. Отключение вывода ошибок в production — сообщения об ошибках не должны попадать в ответ клиенту. Логируйте их на сервере.
  4. Использование WAF — веб-приложения firewall могут блокировать известные шаблоны атак, но не заменяют исправление уязвимостей.
  5. Регулярное обновление СУБД и фреймворков — закрывайте известные уязвимости.

Пример безопасного кода

Вместо конкатенации строк используйте параметризацию. Например, на PHP с PDO:

$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
$stmt->execute(['id' => $userId]);

Такой подход полностью исключает возможность SQL-инъекции, включая error-based.

Частые вопросы

Почему используется именно EXTRACTVALUE?

Функция EXTRACTVALUE доступна в MySQL и при передаче некорректного XML генерирует ошибку с указанием проблемного фрагмента. Это удобно для атакующего, так как в ошибке отображается переданная строка.

Что означает 8503 в запросе?

Это произвольное число, первый аргумент функции. Оно не несёт смысловой нагрузки, кроме как быть допустимым аргументом.

Можно ли использовать эту технику на других СУБД?

PostgreSQL, MS SQL и Oracle имеют свои аналоги error-based инъекций, но синтаксис и функции отличаются.

Заключение

Строка OR EXTRACTVALUE(8503,CONCAT(0x7e,((SELECT (ELT(8503=8503,1)))),0x7e))-- - — это не случайный набор символов, а тщательно сконструированный эксплойт для извлечения данных из MySQL через сообщения об ошибках. Понимание таких атак помогает разработчикам писать безопасный код и защищать веб-приложения. Главное правило: никогда не доверяйте пользовательскому вводу и всегда используйте параметризованные запросы.

Источники