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

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

Цель такой инъекции — заставить базу данных вернуть сообщение об ошибке, содержащее полезные данные (например, имя пользователя, версию БД, названия таблиц). Функция EXTRACTVALUE специально провоцирует ошибку формата XPath, и в тексте ошибки MySQL отображает переданное ей значение. Это позволяет атакующему пошагово извлекать информацию из базы.

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

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

Если XPath-выражение некорректно, MySQL генерирует ошибку вида: XPATH syntax error: '...'. В этой ошибке отображается часть переданного XPath-выражения. Злоумышленники пользуются этим, чтобы вывести в сообщении об ошибке результат подзапроса.

Пример: EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e)) вернёт ошибку, содержащую версию MySQL, обрамлённую символами тильды (~).

Разбор конкретного запроса

Рассмотрим запрос: ")) OR EXTRACTVALUE(3217,CONCAT(0x7e,((SELECT (ELT(3217=3217,1)))),0x7e))-- -

  • ")) — закрывает предыдущие скобки и кавычки в уязвимом запросе, чтобы внедрить свой код.
  • OR — логический оператор, который делает условие всегда истинным (если подзапрос вернёт что-то).
  • EXTRACTVALUE(3217, ...) — вызов функции для генерации ошибки. Первый аргумент (3217) — произвольное число, не являющееся корректным XML.
  • CONCAT(0x7e, ((SELECT (ELT(3217=3217,1)))), 0x7e) — формирует строку для XPath. 0x7e — это шестнадцатеричный код символа тильды (~).
  • ELT(3217=3217,1) — функция ELT возвращает N-й элемент из списка. Здесь условие 3217=3217 всегда истинно (1), поэтому ELT(1,1) вернёт 1. Это простейший пример, но на практике вместо 1 подставляется подзапрос, извлекающий данные (например, (SELECT user())).
  • -- - — комментарий, обрезающий остаток оригинального SQL-запроса.

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

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

Процесс извлечения данных через error-based SQL-инъекцию с EXTRACTVALUE обычно включает несколько шагов:

  1. Определение точки инъекции. Атакующий проверяет, обрабатывает ли приложение ввод и возвращает ли ошибки СУБД.
  2. Вывод версии MySQL. Например: AND EXTRACTVALUE(1, CONCAT(0x7e, version(), 0x7e)).
  3. Получение имени текущей базы данных. AND EXTRACTVALUE(1, CONCAT(0x7e, database(), 0x7e)).
  4. Извлечение имён таблиц и столбцов. С помощью подзапросов к information_schema.tables и information_schema.columns.
  5. Дамп данных. Построчный вывод содержимого таблиц с использованием LIMIT и смещения.

Важно: EXTRACTVALUE возвращает не более 32 символов в сообщении об ошибке, поэтому для длинных строк используются функции SUBSTRING или MID.

Другие функции для error-based инъекций

Помимо EXTRACTVALUE, в MySQL часто используются:

  • UPDATEXML() — аналогична EXTRACTVALUE, но генерирует ошибку через обновление XML.
  • GTID_SUBSET() — в некоторых версиях MySQL позволяет вывести данные в ошибке.
  • EXP() — вызывает ошибку переполнения, если передать большое число.
  • FLOOR(RAND(0)*2) — классический метод с группировкой, вызывающий дублирование ключа.

Однако EXTRACTVALUE и UPDATEXML считаются наиболее удобными, так как позволяют напрямую выводить произвольные строки.

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

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

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

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

Заключение

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

Источники