Введение

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

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

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

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

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

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

Рассмотрим каждый элемент запроса:

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

Функция EXTRACTVALUE

Синтаксис: EXTRACTVALUE(XML_fragment, XPath_expression). Функция возвращает текст из XML-фрагмента, соответствующий XPath-выражению. Если XPath-выражение содержит недопустимые символы (например, ~), MySQL генерирует ошибку вида: XPATH syntax error: '~...~'. Именно эта ошибка и содержит внедрённые данные.

Функция CONCAT

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

Подзапрос с ELT

SELECT (ELT(7091=7091,1)) — это подзапрос, который возвращает число 1. Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Если N=1, возвращается первая строка. В данном случае условие 7091=7091 всегда истинно, поэтому ELT возвращает 1. Это простейший пример; в реальных атаках вместо 1 может быть подзапрос, извлекающий данные (например, версию БД, имя пользователя, хеши паролей).

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

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

SELECT * FROM users WHERE name LIKE '%");

Злоумышленник подставляет вместо % строку %") AND EXTRACTVALUE(7091,CONCAT(0x7e,((SELECT (ELT(7091=7091,1)))),0x7e))-- -. В результате запрос становится:

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

MySQL выполняет функцию EXTRACTVALUE, которая вызывает ошибку. В ответе сервера появится сообщение:

XPATH syntax error: '~1~'

Таким образом, атакующий видит результат выполнения подзапроса — в данном случае 1. Заменив ELT(7091=7091,1) на что-то вроде (SELECT version()), он получит версию СУБД. Аналогично можно извлекать имена таблиц, столбцов и любые другие данные.

Опасность и последствия

Error-based SQL-инъекции через EXTRACTVALUE позволяют злоумышленнику:

  • Получить информацию о структуре базы данных.
  • Извлечь конфиденциальные данные (логины, пароли, персональные данные).
  • В некоторых случаях — выполнить произвольные SQL-запросы, вплоть до удаления или изменения данных.

Эта техника особенно опасна, потому что не требует слепого подбора и даёт быстрый результат. Ошибки СУБД часто отображаются прямо на странице, что упрощает атаку.

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

Основные меры защиты от SQL-инъекций:

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

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

Заключение

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

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

Источники