Что такое SQL-инъекция с EXTRACTVALUE?

Встречая в логах или в поле ввода строку вида %')))) AND EXTRACTVALUE(7002,CONCAT(0x7e,((SELECT (ELT(7002=7002,1)))),0x7e))-- -, многие задаются вопросом: что это и какова её цель? Это классический пример SQL-инъекции, нацеленной на базы данных MySQL. Злоумышленник пытается внедрить вредоносный код в SQL-запрос, чтобы получить доступ к данным или вызвать ошибку, раскрывающую информацию.

В данной статье мы подробно разберём этот payload, объясним, как работает функция EXTRACTVALUE, и расскажем, как защититься от подобных атак.

Как работает SQL-инъекция?

SQL-инъекция (SQL injection) — один из самых распространённых способов взлома веб-приложений. Она возникает, когда пользовательские данные попадают в SQL-запрос без должной обработки. В результате атакующий может изменить логику запроса, выполнить произвольные команды или извлечь конфиденциальную информацию.

Пример уязвимого кода на PHP:

$id = $_GET['id'];
$query = "SELECT * FROM users WHERE id = '$id'";

Если передать в параметр id строку 1' OR '1'='1, запрос вернёт всех пользователей. Более сложные payload'ы позволяют извлекать данные посимвольно или вызывать ошибки для получения информации.

Разбор payload с EXTRACTVALUE

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

%')))) AND EXTRACTVALUE(7002,CONCAT(0x7e,((SELECT (ELT(7002=7002,1)))),0x7e))-- -

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

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

Таким образом, payload заставляет базу данных выполнить EXTRACTVALUE с некорректным XPath-выражением (символ ~ не является допустимым), что приводит к ошибке. В сообщении об ошибке MySQL выводит переданную строку, в данном случае ~1~. Если вместо 1 подставить подзапрос, например (SELECT version()), то в ошибке появится версия СУБД. Это классическая error-based SQL-инъекция.

Функция EXTRACTVALUE в MySQL

Функция EXTRACTVALUE() предназначена для извлечения значения из XML-документа по заданному XPath-выражению. Синтаксис:

EXTRACTVALUE(xml_frag, xpath_expr)

Она принимает фрагмент XML-разметки и XPath-локатор, возвращая текст первого узла, соответствующего выражению. Например:

SELECT EXTRACTVALUE('текст', '/a/b');
-- Результат: текст

Однако при передаче некорректного XPath (например, содержащего символ ~) MySQL генерирует ошибку XPATH syntax error, в тексте которой отображается переданное значение. Это и используется злоумышленниками для извлечения данных.

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

Цели и последствия атаки

Основные цели злоумышленника:

  • Получение версии базы данных, имён таблиц и колонок.
  • Извлечение учётных данных пользователей, хешей паролей, персональной информации.
  • Модификация или удаление данных.
  • Обход аутентификации и получение прав администратора.

Успешная SQL-инъекция может привести к полной компрометации базы данных, утечке конфиденциальной информации и финансовым потерям.

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

Основные меры защиты:

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

Также рекомендуется проводить аудит кода и пентесты для выявления уязвимостей.

Пример безопасного кода на PHP

Вместо конкатенации используйте подготовленные выражения:

$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
$stmt->execute(['id' => $id]);
$user = $stmt->fetch();

Такой подход гарантирует, что пользовательский ввод не изменит структуру запроса.

Заключение

Строка с EXTRACTVALUE — это не случайный набор символов, а тщательно сконструированный payload для эксплуатации уязвимости SQL-инъекции в MySQL. Понимание принципов работы таких атак помогает разработчикам и администраторам своевременно принимать меры защиты. Помните: безопасность базы данных — это не только техническая, но и организационная задача, требующая постоянного внимания.

Источники