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

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

В отличие от UNION-инъекций, где результат внедряется в вывод страницы, error-based метод заставляет сервер вернуть сообщение об ошибке с внедрёнными данными. Это делает его мощным инструментом в арсенале пентестеров и хакеров.

Разбор структуры запроса

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

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

При выполнении такого запроса MySQL попытается обработать строку ~1~ как XML, что вызовет ошибку вида: XPATH syntax error: '~1~'. В реальной атаке вместо «1» подставляется результат подзапроса, извлекающего имена таблиц, колонок или пароли.

Как это работает на практике

Предположим, уязвимый запрос выглядит так:

SELECT * FROM users WHERE id = '$id';

Злоумышленник передаёт в параметр $id строку 1 AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e))-- -. В результате СУБД выполнит:

SELECT * FROM users WHERE id = '1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e))-- -';

Функция EXTRACTVALUE получит строку ~имя_базы~, которая не является валидным XML. MySQL сгенерирует ошибку, и в сообщении об ошибке будет указано: XPATH syntax error: '~имя_базы~'. Так злоумышленник узнаёт имя текущей базы данных.

Пошаговое извлечение информации

  1. Определение версии MySQL: AND EXTRACTVALUE(1, CONCAT(0x7e, version(), 0x7e))-- -
  2. Получение имени базы: AND EXTRACTVALUE(1, CONCAT(0x7e, database(), 0x7e))-- -
  3. Извлечение таблиц: AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1), 0x7e))-- -
  4. Дамп колонок и данных: аналогично, с изменением LIMIT.

Использование ELT в исходном примере — это упрощённый тестовый вариант, показывающий, что инъекция возможна. В реальных атаках подзапросы сложнее и нацелены на конкретные данные.

Важно: подобные строки часто встречаются в логах веб-серверов, WAF или систем мониторинга. Если вы видите такой запрос в своих логах — это попытка взлома, и стоит немедленно проверить безопасность приложения.

Почему EXTRACTVALUE уязвима?

Функция EXTRACTVALUE (а также UPDATEXML) исторически используется для error-based инъекций. Она принимает два аргумента: XML-документ и XPath-выражение. Если XPath-выражение содержит недопустимые символы, MySQL возвращает ошибку с фрагментом переданной строки. Это позволяет внедрять произвольные данные в текст ошибки.

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

Альтернативные error-based функции

  • UPDATEXML — аналогичный механизм, но с возможностью обновления XML.
  • GTID_SUBSET, JSON_KEYS и другие — используются в более новых версиях для генерации ошибок.
  • EXP — переполнение через математическую функцию.

Строка с ELT(9912=9912,1) — это простейший пример, демонстрирующий работоспособность инъекции. В реальных условиях злоумышленники комбинируют функции для обхода фильтров.

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

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

Дополнительные меры:

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

Что делать, если вы обнаружили такую строку в логах?

Если вы администратор и видите подобные записи в логах, это сигнал о попытке взлома. Немедленно:

  1. Проверьте, не была ли атака успешной: поищите необычные ошибки в логах приложения, аномальные запросы к БД.
  2. Проанализируйте уязвимый скрипт: возможно, он использует конкатенацию строк для построения SQL-запросов.
  3. Внедрите параметризованные запросы во всех местах работы с БД.
  4. Ограничьте права пользователя БД, от имени которого работает приложение.
  5. Настройте WAF для блокировки известных сигнатур error-based инъекций.

Помните: даже если атака не удалась, она указывает на наличие уязвимости, которую необходимо устранить.

Заключение

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

Используйте параметризованные запросы, обновляйте СУБД и следите за логами — это базовые шаги к безопасности вашего веб-приложения.

Источники