Что такое EXTRACTVALUE и при чём тут SQL-инъекция?
Функция EXTRACTVALUE в MySQL предназначена для извлечения значения из XML-строки по заданному XPath-выражению. Однако при неправильной обработке пользовательского ввода она становится мощным инструментом для так называемых error-based SQL-инъекций. Злоумышленники используют её для получения данных из базы через сообщения об ошибках, которые возвращает сервер.
Запрос AND EXTRACTVALUE(4597,CONCAT(0x7e,((SELECT (ELT(4597=4597,1)))),0x7e))-- - — это классический пример такой инъекции. Давайте разберём его по частям.
Разбор конструкции по элементам
1. Начало: AND
Оператор AND добавляется к легитимному SQL-запросу, чтобы внедрить дополнительное условие. Если исходный запрос был, например, SELECT * FROM users WHERE id = 1, то после подстановки получается SELECT * FROM users WHERE id = 1 AND EXTRACTVALUE(...). Это позволяет выполнить вредоносную функцию только при истинности предыдущего условия.
2. Функция EXTRACTVALUE(4597, ...)
Первый аргумент — 4597 — это произвольное число, которое не является корректным XML-документом. Второй аргумент — XPath-выражение, которое мы конструируем динамически. Когда MySQL пытается извлечь значение из не-XML строки, он генерирует ошибку. Именно на этом строится атака: в тексте ошибки можно вывести произвольные данные.
3. CONCAT(0x7e, ((SELECT (ELT(4597=4597,1)))), 0x7e)
CONCAT объединяет несколько строк. Здесь используется шестнадцатеричный код 0x7e, который соответствует символу тильды ~. Тильда служит маркером, по которому потом легко найти выведенные данные в сообщении об ошибке.
Внутри CONCAT находится подзапрос (SELECT (ELT(4597=4597,1))). Разберём и его:
- ELT(N, str1, str2, ...) — функция MySQL, возвращающая N-ю строку из списка. Если N=1, возвращается первая строка, если N=2 — вторая и т.д.
- 4597=4597 — это логическое выражение, которое всегда истинно, поэтому в MySQL оно преобразуется в 1. Таким образом,
ELT(1, 1)вернёт строку'1'.
В реальной атаке вместо 1 подставляются имена таблиц, колонок или другие данные, которые нужно извлечь. Например, ELT(1, (SELECT table_name FROM information_schema.tables LIMIT 1)).
4. Завершение: -- -
Двойной дефис с пробелом или без — это комментарий в SQL. Он «отрезает» остаток оригинального запроса, чтобы синтаксис остался корректным. Символ - после пробела добавлен для обхода некоторых фильтров, которые могут удалять -- без пробела.
Как это работает на практике
Предположим, уязвимый запрос выглядит так:
SELECT * FROM articles WHERE id = 1 AND EXTRACTVALUE(4597,CONCAT(0x7e,((SELECT (ELT(4597=4597,1)))),0x7e))-- -
MySQL выполнит функцию EXTRACTVALUE с первым аргументом 4597, который не является XML. Второй аргумент — строка вида ~1~. При попытке извлечь XPath из не-XML возникнет ошибка:
XPATH syntax error: '~1~'
В сообщении об ошибке мы видим ~1~. Если заменить ELT(4597=4597,1) на подзапрос, возвращающий, например, версию базы данных (SELECT version()), то в ошибке появится версия MySQL. Так пошагово злоумышленник может извлечь любые данные: имена таблиц, логины, пароли.
Зачем это нужно злоумышленнику?
Error-based инъекции через EXTRACTVALUE (и аналогичную функцию UPDATEXML) позволяют обходить фильтры, которые блокируют UNION-запросы или слепые инъекции. Они дают быстрый отклик: не нужно перебирать символы по одному, как в blind SQLi — сервер сам возвращает данные в тексте ошибки. Это делает атаку эффективной и опасной.
Как защититься от подобных инъекций?
- Используйте подготовленные выражения (prepared statements). Это самый надёжный способ. Параметризованные запросы не позволяют пользовательскому вводу влиять на структуру SQL.
- Экранируйте специальные символы. Если по каким-то причинам нельзя использовать prepared statements, применяйте функции экранирования, например
mysqli_real_escape_string. - Ограничьте права пользователя БД. Учётная запись, от имени которой работает приложение, не должна иметь прав на чтение
information_schemaили системных таблиц. - Включите логирование и мониторинг. Подозрительные запросы с EXTRACTVALUE, CONCAT, ELT должны вызывать тревогу.
- Обновляйте СУБД. В новых версиях MySQL некоторые функции могут быть отключены или работать иначе, но полагаться только на это нельзя.
Вывод
Запрос AND EXTRACTVALUE(4597,CONCAT(0x7e,((SELECT (ELT(4597=4597,1)))),0x7e))-- - — это не случайный набор символов, а тщательно сконструированная полезная нагрузка для error-based SQL-инъекции. Она эксплуатирует функцию EXTRACTVALUE для вывода данных через сообщения об ошибках. Понимание таких конструкций помогает разработчикам и специалистам по безопасности лучше защищать свои приложения. Никогда не доверяйте пользовательскому вводу и всегда используйте параметризованные запросы.
Комментарии
—Войдите, чтобы оставить комментарий