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

SQL-инъекция остаётся одной из самых опасных уязвимостей веб-приложений. Согласно OWASP Top 10, она входит в список критических рисков. Один из методов эксплуатации — error-based SQL-инъекция с использованием функции EXTRACTVALUE() в MySQL. Этот приём позволяет злоумышленнику извлекать данные из базы, вызывая ошибки, которые выводятся на страницу.

Функция EXTRACTVALUE(XML_fragment, XPath_expression) извлекает значение из XML-строки по заданному XPath-выражению. Если XPath-выражение некорректно, MySQL возвращает ошибку с текстом, содержащим переданные данные. Это и используется для получения информации.

Синтаксис и принцип работы

Рассмотрим запрос из вашего вопроса:

%' OR EXTRACTVALUE(4210,CONCAT(0x7e,((SELECT (ELT(4210=4210,1)))),0x7e))-- -

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

  • %' — закрывает строковый литерал в уязвимом параметре.
  • OR — логический оператор для внедрения условия.
  • EXTRACTVALUE(4210, ...) — первый аргумент — произвольное число (4210), второй — XPath-выражение, которое вызывает ошибку.
  • CONCAT(0x7e, ..., 0x7e) — объединяет тильды (~) с результатом подзапроса. Тильды помогают отделить данные в сообщении об ошибке.
  • (SELECT (ELT(4210=4210,1))) — подзапрос, возвращающий 1, если условие истинно. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 4210=4210 всегда истинно, поэтому возвращается 1.
  • -- - — комментарий, обрезающий остаток запроса.

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

Как эксплуатируется error-based SQLi

Главная цель — заставить базу данных вернуть нужные данные в сообщении об ошибке. Вместо константы 1 в подзапрос подставляются имена таблиц, колонок или конкретные значения. Например, для получения имени текущей базы данных:

%' OR EXTRACTVALUE(1,CONCAT(0x7e,(SELECT database()),0x7e))-- -

Ошибка покажет: XPATH syntax error: '~имя_базы~'. Аналогично можно извлечь версию MySQL, имя пользователя, названия таблиц из information_schema.tables и даже хеши паролей.

Для посимвольного извлечения данных применяют функции SUBSTRING() и LIMIT. Например, чтобы получить имя первой таблицы:

%' OR EXTRACTVALUE(1,CONCAT(0x7e,(SELECT table_name FROM information_schema.tables LIMIT 0,1),0x7e))-- -

Меняя значение LIMIT (0,1 → 1,1 и т.д.), перебирают все таблицы.

Ограничения и альтернативы

Метод EXTRACTVALUE работает только в MySQL и MariaDB до версии 5.7 включительно. В более новых версиях (MySQL 8.0+) функция EXTRACTVALUE удалена, и error-based инъекции через неё невозможны. Однако существуют другие функции, вызывающие ошибки с данными: UPDATEXML(), GTID_SUBSET(), JSON_KEYS() и т.д.

Если приложение не выводит ошибки базы данных, злоумышленник может использовать blind SQL-инъекции (boolean-based или time-based), которые медленнее, но тоже эффективны.

Пример реальной атаки

Предположим, сайт имеет параметр id=1 и уязвим. Злоумышленник отправляет:

id=1' AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT user()),0x7e))-- -

В ответе появляется ошибка с именем пользователя БД, например ~admin@localhost~. Затем атакующий перебирает таблицы, колонки и извлекает логины/пароли. Это может привести к полному захвату сайта.

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

Основной метод — использование параметризованных запросов (prepared statements). Они разделяют код и данные, поэтому внедрение команд невозможно. В PHP это PDO или mysqli с подготовленными выражениями, в Java — PreparedStatement, в Python — параметризованные курсоры.

  • Валидация входных данных: проверяйте типы, форматы, белые списки допустимых значений.
  • Экранирование: используйте функции экранирования спецсимволов, но это менее надёжно, чем параметризация.
  • Минимальные привилегии: учётная запись БД для веб-приложения не должна иметь прав на чтение системных таблиц или выполнение опасных операций.
  • Отключение вывода ошибок: не показывайте пользователям сообщения СУБД, логируйте их на сервере.
  • WAF: веб-приложения-экраны могут блокировать подозрительные запросы, но не заменяют исправление кода.

Регулярно проводите аудит кода и пентесты, чтобы выявлять уязвимости до злоумышленников.

Вывод

Конструкция %' OR EXTRACTVALUE(...)-- - — классический пример error-based SQL-инъекции в MySQL. Она позволяет быстро извлекать данные через сообщения об ошибках. Понимание этого метода помогает разработчикам осознать важность параметризованных запросов и других мер защиты. Никогда не доверяйте пользовательскому вводу и всегда используйте безопасные API для работы с базами данных.

Источники