Что такое SQL-инъекция через ExtractValue?

SQL-инъекция — один из самых распространённых способов атаки на веб-приложения, при котором злоумышленник внедряет вредоносный код в SQL-запросы. Особый интерес представляет техника, основанная на функции ExtractValue в СУБД MySQL. Она позволяет извлекать данные из XML-документа, но при неправильном использовании становится инструментом для кражи информации из базы данных.

В запросе пользователя: %" AND EXTRACTVALUE(3835,CONCAT(0x7e,((SELECT (ELT(3835=3835,1)))),0x7e))-- - — как раз демонстрируется классический пример error-based SQL-инъекции. Давайте разберём его по частям.

Анатомия вредоносного запроса

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

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

Если приложение уязвимо, MySQL попытается обработать этот XML-путь и выдаст ошибку, содержащую результат подзапроса. Так злоумышленник может извлекать данные посимвольно.

Как работает ExtractValue в MySQL

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

В нашем примере XPath-выражение формируется динамически: CONCAT(0x7e, (SELECT ...), 0x7e) создаёт строку типа ~1~. Поскольку это невалидный XPath, MySQL выдаст ошибку, содержащую эту строку. Если вместо 1 подставить, например, имя пользователя или версию базы, они окажутся в тексте ошибки.

⚠️ Важно: подобные запросы — не просто теория. Это реальный инструмент, который используют пентестеры и злоумышленники для анализа защищённости веб-приложений.

Пошаговый разбор подзапроса

Центральная часть — SELECT (ELT(3835=3835,1)). Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь N — результат сравнения 3835=3835, то есть TRUE (в MySQL это 1). Список состоит из одного элемента — 1. Таким образом, подзапрос всегда возвращает 1.

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

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

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

Если SQL-инъекция через ExtractValue срабатывает, злоумышленник может:

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

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

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

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

  1. Валидация и фильтрация входных данных — проверяйте типы, длины, допустимые символы.
  2. Экранирование специальных символов — если параметризация невозможна, используйте функции экранирования, предоставляемые драйвером БД.
  3. Ограничение прав пользователя БД — приложение должно работать с минимально необходимыми привилегиями, без доступа к information_schema и системным таблицам.
  4. Отключение вывода ошибок БД — не показывайте пользователям детали ошибок; логируйте их отдельно.
  5. Регулярное обновление СУБД и фреймворков — закрывайте известные уязвимости.

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

Заключение

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

Помните: безопасность веб-приложений — это не разовое мероприятие, а постоянный процесс. Используйте современные методы защиты и следите за обновлениями.

Источники