Что такое EXTRACTVALUE и при чём тут SQL-инъекция?
Функция EXTRACTVALUE в MySQL предназначена для извлечения значения из XML-строки по указанному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_документ, XPath_выражение). Однако при некорректном XPath-выражении MySQL генерирует ошибку, в тексте которой может отображаться переданное выражение. Этим пользуются злоумышленники для проведения error-based SQL-инъекций — атак, при которых данные извлекаются через сообщения об ошибках базы данных.
Запрос %')))) AND EXTRACTVALUE(4610,CONCAT(0x7e,((SELECT (ELT(4610=4610,1)))),0x7e))-- - — это классический пример такой инъекции. Разберём его по частям.
Детальный разбор запроса
1. Начало: %'))))
Символы %, ', ) — это попытка закрыть ранее открытые кавычки и скобки в уязвимом SQL-запросе. Например, если исходный запрос выглядел как SELECT * FROM users WHERE name = '...', то последовательность %')))) может закрыть строковый литерал и несколько вложенных функций, чтобы внедрить собственный код.
2. AND EXTRACTVALUE(4610, ...)
Далее добавляется логическое условие AND с вызовом EXTRACTVALUE. Первый аргумент — число 4610 (может быть любым, часто используется как идентификатор). Второй аргумент — конкатенация строки с тильдами 0x7e (символ ~) и подзапроса.
3. CONCAT(0x7e, ((SELECT (ELT(4610=4610,1)))), 0x7e)
Здесь формируется XPath-выражение, которое заведомо вызовет ошибку. 0x7e — шестнадцатеричное представление символа ~. Внутри — подзапрос SELECT (ELT(4610=4610,1)). Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае 4610=4610 — это истина (1), поэтому ELT(1,1) вернёт 1. Подзапрос вернёт число 1, которое преобразуется в строку '1'.
Итоговое XPath-выражение: ~1~. Это невалидный XPath, поэтому MySQL сгенерирует ошибку вида: XPATH syntax error: '~1~'. В сообщении об ошибке отобразится результат подзапроса. В реальной атаке вместо ELT(4610=4610,1) подставляются другие выражения, например, SELECT version() или SELECT table_name FROM information_schema.tables, чтобы извлечь данные.
4. Комментарий -- -
Два дефиса и пробел (или -- -) — это комментарий в SQL, который отсекает оставшуюся часть оригинального запроса, чтобы не возникло синтаксической ошибки.
Зачем это нужно злоумышленнику?
Error-based SQL-инъекции позволяют быстро получать информацию из базы данных, если приложение выводит сообщения об ошибках СУБД на страницу. В отличие от blind-инъекций, здесь не нужно перебирать символы по одному — данные возвращаются в тексте ошибки. Функция EXTRACTVALUE — один из популярных инструментов для таких атак, наряду с UPDATEXML и GTID_SUBSET.
Как защититься?
- Используйте подготовленные выражения (prepared statements) с параметризацией. Это самый надёжный способ предотвратить SQL-инъекции.
- Отключите вывод ошибок СУБД в production-окружении. Ошибки должны логироваться, но не показываться пользователю.
- Применяйте ORM или библиотеки, которые автоматически экранируют входные данные.
- Проводите регулярные сканирования уязвимостей (например, с помощью sqlmap) и аудит кода.
- Ограничьте права пользователя БД: не давайте приложению доступ к information_schema без необходимости.
Важно: даже если ошибки не выводятся, злоумышленник может использовать blind-техники. Поэтому параметризация запросов обязательна.
Пример уязвимого кода на PHP
$id = $_GET['id'];
$query = "SELECT * FROM products WHERE id = '$id'";
$result = mysqli_query($conn, $query);
Если передать id=1' AND EXTRACTVALUE(4610,CONCAT(0x7e,(SELECT version()),0x7e))-- -, то в случае вывода ошибок на страницу мы увидим версию MySQL.
Заключение
Запрос %')))) AND EXTRACTVALUE(4610,CONCAT(0x7e,((SELECT (ELT(4610=4610,1)))),0x7e))-- - — это учебный пример error-based SQL-инъекции через функцию EXTRACTVALUE. Понимание таких конструкций помогает разработчикам и пентестерам выявлять и устранять уязвимости. Помните: безопасность приложения начинается с отказа от конкатенации SQL-запросов и перехода на параметризованные запросы.
Комментарии
—Войдите, чтобы оставить комментарий