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

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

Запрос %') AND EXTRACTVALUE(1422,CONCAT(0x7e,((SELECT (ELT(1422=1422,1)))),0x7e))-- - — это классический пример внедрения в параметр, который подставляется в SQL-запрос без должной фильтрации.

Разбор синтаксиса запроса

Давайте разберём каждую часть этого запроса по порядку.

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

Как работает атака

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

В данном конкретном примере подзапрос возвращает просто 1, что демонстрирует работоспособность метода. На практике злоумышленник заменил бы 1 на (SELECT password FROM users LIMIT 1) и получил бы пароль в сообщении об ошибке.

Зачем нужен CONCAT и 0x7e?

Символ ~ (тильда) используется как маркер, чтобы облегчить извлечение данных из сообщения об ошибке. XPath-парсер MySQL выводит ошибку в формате: XPATH syntax error: 'значение'. Тильды помогают быстро найти начало и конец полезной нагрузки. CONCAT собирает все части в одну строку, которая затем передаётся как XPath.

Функция ELT и её роль

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

Какие уязвимости эксплуатирует запрос?

Основная причина — отсутствие параметризации запросов. Если веб-приложение подставляет пользовательский ввод напрямую в SQL-строку, оно уязвимо. Конкретно здесь эксплуатируется:

  • Некорректная обработка спецсимволов (кавычки, скобки).
  • Отсутствие экранирования.
  • Использование устаревших функций MySQL, которые не отключены (EXTRACTVALUE доступна, но помечена как deprecated в MySQL 5.7+).

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

Вот основные меры:

  1. Параметризованные запросы (prepared statements). Это самый надёжный способ. Данные передаются отдельно от SQL-кода, и внедрение становится невозможным.
  2. Экранирование специальных символов. Если параметризация невозможна, используйте функции экранирования (например, mysqli_real_escape_string).
  3. Валидация входных данных. Проверяйте, что вводимые данные соответствуют ожидаемому формату (число, email и т.д.).
  4. Отключение опасных функций. Если EXTRACTVALUE не используется в приложении, её можно отключить или ограничить права пользователя БД.
  5. Использование ORM. Современные ORM (например, Doctrine, Hibernate) автоматически параметризуют запросы.
  6. Регулярные аудиты безопасности. Сканеры уязвимостей помогут выявить SQL-инъекции.

Заключение

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

Источники