Введение

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

Что такое EXTRACTVALUE?

Функция EXTRACTVALUE в MySQL предназначена для извлечения значения из XML-документа по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_document, XPath_expression). Она возвращает текст узла, соответствующего XPath. Однако при некорректном XPath-выражении MySQL генерирует ошибку, которая может содержать полезную информацию. Именно это свойство и используется в error-based SQL-инъекциях.

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

Рассмотрим структуру запроса:

  • OR — логический оператор, добавляемый к оригинальному запросу для внедрения условия.
  • EXTRACTVALUE(4137, CONCAT(0x7e, ((SELECT (ELT(4137=4137,1)))), 0x7e)) — вызов функции с двумя аргументами: первый — произвольное число 4137 (может быть любым), второй — конкатенация строк.
  • -- - — комментарий, который игнорирует оставшуюся часть оригинального SQL-запроса.

Первый аргумент 4137 не играет роли, так как XML-документ невалиден, но это не важно. Второй аргумент — результат CONCAT(0x7e, ((SELECT (ELT(4137=4137,1)))), 0x7e). Здесь 0x7e — шестнадцатеричное представление символа ~ (тильда). Он используется как разделитель, чтобы облегчить извлечение данных из сообщения об ошибке.

Функция ELT и условие 4137=4137

ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В нашем случае ELT(4137=4137, 1): выражение 4137=4137 истинно, что в MySQL интерпретируется как 1. Значит, ELT вернёт первую строку — 1. Это простой способ получить константу, но в реальных атаках вместо 1 может быть подзапрос, извлекающий данные (например, имя базы данных, хеши паролей).

Конструкция SELECT (ELT(4137=4137,1)) — это подзапрос, возвращающий 1. В более сложных вариантах здесь может быть SELECT database() или SELECT password FROM users LIMIT 1.

Как работает error-based инъекция

Когда MySQL выполняет EXTRACTVALUE с XPath-выражением, содержащим недопустимые символы (например, тильду), он выдаёт ошибку вида: XPATH syntax error: '~1~'. В сообщении об ошибке отображается переданная строка. Если вместо 1 подставить результат подзапроса, например, имя базы данных, то ошибка покажет это имя. Так злоумышленник может пошагово извлекать данные из базы.

В нашем запросе второй аргумент — CONCAT(0x7e, ((SELECT (ELT(4137=4137,1)))), 0x7e) — даст строку ~1~. При вызове EXTRACTVALUE(4137, '~1~') MySQL попытается интерпретировать ~1~ как XPath и выдаст ошибку: XPATH syntax error: '~1~'. Это подтверждает, что инъекция работает.

Зачем нужен комментарий -- -

Символы -- начинают комментарий в SQL (при условии, что после них есть пробел). Пробел и дефис добавлены для надёжности, чтобы комментарий точно распознался. Всё, что идёт после -- -, игнорируется. Это позволяет отсечь остаток оригинального запроса, который мог бы вызвать синтаксическую ошибку.

Пример уязвимого запроса

Предположим, веб-приложение формирует такой SQL-запрос:

SELECT * FROM articles WHERE id = '$id'

Если пользователь передаст в параметр id значение 1 OR EXTRACTVALUE(4137,CONCAT(0x7e,((SELECT (ELT(4137=4137,1)))),0x7e))-- -, то итоговый запрос станет:

SELECT * FROM articles WHERE id = '1 OR EXTRACTVALUE(4137,CONCAT(0x7e,((SELECT (ELT(4137=4137,1)))),0x7e))-- -'

MySQL выполнит условие id = '1' (ложь, если id не 1), затем оператор OR и вызовет EXTRACTVALUE, что приведёт к ошибке, раскрывающей информацию.

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

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

  • Получить версию СУБД, имя текущей базы данных, пользователя.
  • Извлечь содержимое таблиц (логины, пароли, персональные данные).
  • В некоторых случаях выполнить произвольные команды на сервере.

Это критическая уязвимость, которая может привести к полной компрометации системы.

Способы защиты

Чтобы предотвратить подобные атаки, необходимо:

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

Также рекомендуется использовать веб-application firewall (WAF) для фильтрации подозрительных запросов.

Заключение

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

Источники