Что такое AND EXTRACTVALUE в SQL-инъекции?

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

Подобные конструкции часто встречаются в отчётах об уязвимостях и в логах веб-серверов. Они не являются вредоносным кодом сами по себе, но служат индикатором попытки эксплуатации SQL-инъекции. Понимание механики таких запросов помогает разработчикам и администраторам правильно настраивать защиту и интерпретировать события безопасности.

Как работает функция EXTRACTVALUE в MySQL

Функция EXTRACTVALUE() появилась в MySQL 5.1 и предназначена для извлечения данных из XML-документов с помощью выражений XPath. Она принимает два строковых аргумента: фрагмент XML-разметки и XPath-локатор. Возвращает текст (CDATA) первого текстового узла, который является дочерним для элемента или элементов, соответствующих XPath-выражению.

Синтаксис: EXTRACTVALUE( xml_frag, xpath_expr ). Если XPath-выражение некорректно, функция генерирует ошибку.

Именно эта особенность используется в error-based инъекциях: злоумышленник подставляет в XPath-выражение результат подзапроса, и СУБД возвращает сообщение об ошибке, содержащее эти данные. Например, в нашем случае XPath-выражение формируется как CONCAT(0x7e, (SELECT ...), 0x7e), что даёт строку вида ~1~. Функция EXTRACTVALUE пытается интерпретировать её как XPath и терпит неудачу, выводя в ошибке полученную строку.

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

Рассмотрим по частям выражение AND EXTRACTVALUE(3913,CONCAT(0x7e,((SELECT (ELT(3913=3913,1)))),0x7e))-- -:

  • AND — логический оператор, который добавляется к условию WHERE исходного запроса. Если исходный запрос был истинным, добавление AND с функцией, вызывающей ошибку, приведёт к прерыванию выполнения и выводу сообщения об ошибке.
  • EXTRACTVALUE(3913, ...) — первый аргумент 3913 — это произвольное число, которое будет интерпретировано как XML-фрагмент. Оно не является корректным XML, но это не важно, так как ошибка возникнет на этапе разбора XPath.
  • CONCAT(0x7e, ..., 0x7e) — объединяет символ тильды (~, шестнадцатеричный код 0x7e) с результатом подзапроса. Тильда используется как маркер, чтобы облегчить поиск вывода в тексте ошибки.
  • SELECT (ELT(3913=3913,1)) — подзапрос, возвращающий строку 1. Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь N — результат сравнения 3913=3913, то есть 1 (истина). Следовательно, ELT(1, 1) вернёт 1.
  • -- - — комментарий, который отсекает оставшуюся часть исходного SQL-запроса, чтобы не нарушать синтаксис.

В результате MySQL попытается выполнить XPath-выражение ~1~, что вызовет ошибку вида XPATH syntax error: '~1~'. В тексте ошибки злоумышленник увидит 1 — это подтверждает, что инъекция работает и можно извлекать произвольные данные, подставляя вместо ELT(3913=3913,1) другие подзапросы.

Зачем это нужно злоумышленнику?

Error-based SQL-инъекции — один из самых быстрых способов извлечения информации из базы данных. В отличие от blind-инъекций, где данные получают по крупицам через логические условия, здесь сервер сам возвращает результат в сообщении об ошибке. Это позволяет за несколько запросов получить имена таблиц, столбцов, логины и пароли пользователей.

Конструкция с EXTRACTVALUE особенно популярна, потому что функция доступна во многих версиях MySQL и не требует специальных привилегий. Однако начиная с MySQL 5.7.9 она была объявлена устаревшей, а в MySQL 8.0 удалена. Тем не менее, на многих устаревших серверах она всё ещё работает, что делает этот вектор атаки актуальным.

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

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

  • Валидация и фильтрация всех входных данных, особенно тех, что попадают в SQL-запросы.
  • Применение ORM или query builder с автоматическим экранированием.
  • Ограничение прав пользователя базы данных: приложение должно работать от имени учётной записи с минимально необходимыми привилегиями.
  • Регулярное обновление СУБД и отказ от устаревших функций, таких как EXTRACTVALUE.
  • Использование WAF (Web Application Firewall) для блокировки подозрительных запросов, содержащих сигнатуры SQL-инъекций.

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

Часто задаваемые вопросы

Является ли EXTRACTVALUE уязвимостью MySQL?

Сама по себе функция не является уязвимостью. Опасность возникает, когда разработчик позволяет пользовательским данным напрямую попадать в SQL-запрос без экранирования. EXTRACTVALUE лишь служит инструментом для эксплуатации.

Что означает 0x7e в этом выражении?

0x7e — шестнадцатеричное представление символа тильды ~. Он используется как разделитель, чтобы чётко выделить извлекаемое значение в тексте ошибки.

Почему используется 3913=3913?

Это всегда истинное условие. Оно нужно для того, чтобы ELT вернула первую строку (в данном случае 1). В реальной атаке вместо этого подставляются подзапросы, возвращающие нужные данные.

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

Источники