Что такое OR EXTRACTVALUE?

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

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

Разбор строки по частям

Рассмотрим конструкцию детально:

  • OR — логический оператор, который добавляется к исходному запросу, чтобы инъекция сработала в контексте условия WHERE.
  • EXTRACTVALUE(7047, ...) — первый аргумент (7047) — это произвольное число, которое в данном случае служит идентификатором (может быть любым). Второй аргумент — XPath-выражение.
  • CONCAT(0x7e, ((SELECT (ELT(7047=7047,1)))), 0x7e) — функция CONCAT объединяет строки. 0x7e — это шестнадцатеричное представление символа «~» (тильда). ELT(7047=7047,1) — функция ELT возвращает N-й элемент из списка; условие 7047=7047 всегда истинно, поэтому возвращается 1. Таким образом, в XPath попадает строка вида «~1~».
  • -- - — комментарий, который отсекает оставшуюся часть оригинального SQL-запроса, чтобы не возникло синтаксической ошибки.

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

Зачем нужен ELT(7047=7047,1)?

ELT — это функция MySQL, которая возвращает N-й элемент из списка. Синтаксис: ELT(N, str1, str2, ...). Если N=1, возвращается первая строка. Выражение 7047=7047 всегда истинно и в числовом контексте даёт 1. Таким образом, ELT возвращает «1» — это простейший тест, чтобы убедиться, что инъекция работает. В реальных атаках вместо «1» подставляют подзапросы, извлекающие имена таблиц, колонок или данные пользователей.

Как работает error-based SQL-инъекция через EXTRACTVALUE

Механизм атаки следующий:

  1. Злоумышленник находит параметр, который подставляется в SQL-запрос без должной обработки.
  2. В параметр внедряется конструкция с EXTRACTVALUE и подзапросом, извлекающим нужные данные.
  3. СУБД выполняет запрос, и из-за некорректного XPath-выражения возникает ошибка.
  4. Текст ошибки возвращается пользователю (или сохраняется в логах, доступных атакующему), и в нём содержится результат подзапроса.

Это один из самых удобных методов извлечения данных, так как не требует слепого перебора (boolean-based) или временных задержек (time-based). Однако он работает только если приложение выводит сообщения об ошибках СУБД.

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

Помимо EXTRACTVALUE, в MySQL для этих целей используют:

  • UPDATEXML() — также работает с XML и генерирует ошибку при некорректном XPath.
  • GTID_SUBSET(), JSON_KEYS() и другие функции, вызывающие ошибки с полезной нагрузкой.
  • floor() в связке с группировкой — классический пример error-based инъекции.

Все они эксплуатируют одну и ту же идею: заставить СУБД вывести в сообщении об ошибке контролируемые данные.

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

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

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

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

Рассмотрим фрагмент на PHP, который может быть уязвим:

$id = $_GET['id'];
$query = "SELECT * FROM products WHERE id = $id";
$result = mysqli_query($conn, $query);

Если в параметр id передать 1 OR EXTRACTVALUE(7047,CONCAT(0x7e,((SELECT (ELT(7047=7047,1)))),0x7e))-- -, то итоговый запрос станет:

SELECT * FROM products WHERE id = 1 OR EXTRACTVALUE(7047,CONCAT(0x7e,((SELECT (ELT(7047=7047,1)))),0x7e))-- -

MySQL выполнит его и вернёт ошибку с текстом «~1~». Чтобы этого избежать, следует использовать подготовленные выражения:

$stmt = $conn->prepare("SELECT * FROM products WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();

В этом случае любой ввод будет восприниматься как значение, а не как часть SQL-кода.

Заключение

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

Источники

  • SQL Injection — Wikipedia