Что такое SQL-инъекция через EXTRACTVALUE?
SQL-инъекция (SQLi) — один из самых опасных классов веб-уязвимостей, который уже много лет не покидает список OWASP Top 10. Атака позволяет злоумышленнику вмешиваться в выполнение SQL-запросов, читать, изменять или удалять данные. Среди множества техник особое место занимает error-based SQL-инъекция, при которой данные извлекаются через сообщения об ошибках базы данных. Одним из классических инструментов для такой атаки в MySQL является функция EXTRACTVALUE.
В этом материале мы детально разберём конкретный payload: ")) OR EXTRACTVALUE(5781,CONCAT(0x7e,((SELECT (ELT(5781=5781,1)))),0x7e))-- - — объясним, из каких частей он состоит, зачем нужны функции CONCAT и ELT, и как защитить приложение от подобных атак.
Функция EXTRACTVALUE в MySQL
EXTRACTVALUE — это встроенная функция MySQL, предназначенная для работы с XML. Она извлекает значение из фрагмента XML-документа по заданному XPath-выражению. Синтаксис прост:
EXTRACTVALUE(XML_frag, XPath_expr)
Функция возвращает текстовое содержимое узла, соответствующего XPath. Если XPath-выражение синтаксически некорректно, MySQL генерирует ошибку XPATH syntax error и включает в сообщение фрагмент переданного выражения. Именно эта особенность и делает EXTRACTVALUE идеальным инструментом для error-based инъекций: атакующий может «подсунуть» в XPath-аргумент результат подзапроса, и сервер вернёт его в тексте ошибки.
Важно: начиная с MySQL 5.7 функция EXTRACTVALUE помечена как устаревшая (deprecated), а в MySQL 8.0 удалена. Однако множество legacy-систем до сих пор работают на старых версиях, поэтому угроза сохраняется.
Разбор payload по частям
Рассмотрим строку ")) OR EXTRACTVALUE(5781,CONCAT(0x7e,((SELECT (ELT(5781=5781,1)))),0x7e))-- - поэлементно.
1. Закрывающие скобки и кавычки: "))
Символы ")) нужны, чтобы «закрыть» оригинальный SQL-запрос приложения. Разработчик, скорее всего, использовал конструкцию вида WHERE id = ("$input"). Атакующий подставляет свои символы, чтобы синтаксис остался корректным, и добавляет логический оператор OR.
2. Оператор OR
OR присоединяет вредоносное условие к существующему WHERE. Если исходное условие ложно, OR с внедрённым выражением может вернуть истину — или, как в нашем случае, вызвать выполнение опасной функции.
3. EXTRACTVALUE(5781, CONCAT(...))
Первый аргумент — произвольное число 5781 (может быть любым). Второй аргумент — результат CONCAT. Поскольку XPath-выражение формируется динамически и содержит запрещённые символы, MySQL сгенерирует ошибку, в тексте которой окажется результат вложенного подзапроса.
4. CONCAT(0x7e, ..., 0x7e)
CONCAT склеивает строки. 0x7e — это шестнадцатеричное представление символа ~ (тильда). Тильды используются как маркеры-обёртки: они помогают атакующему легко найти извлечённые данные в длинном сообщении об ошибке. Всё, что находится между двумя тильдами, — это результат подзапроса.
5. (SELECT (ELT(5781=5781,1)))
ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Выражение 5781=5781 всегда истинно и в числовом контексте даёт 1. Значит, ELT(1, 1) вернёт первый элемент — строку "1". В реальной атаке вместо константы 1 подставляется подзапрос, извлекающий данные (например, имя базы, версию СУБД или хеши паролей). Здесь приведён «тестовый» вариант для проверки уязвимости: если сервер вернёт ошибку с тильдами и единицей внутри, точка инъекции подтверждена.
6. Комментарий -- -
Двойной дефис с пробелом (или -- -) — это комментарий в SQL. Он «отрезает» остаток оригинального запроса, чтобы лишние кавычки и скобки не сломали синтаксис. Пробел после -- обязателен в MySQL.
Как выглядит успешная атака
Если приложение уязвимо, в ответе сервера появится сообщение об ошибке вида:
XPATH syntax error: '~1~'
Атакующий видит: инъекция работает, данные выводятся. Далее вместо 1 он подставляет, например, SELECT version() или SELECT table_name FROM information_schema.tables LIMIT 1 — и посимвольно (или сразу) извлекает конфиденциальную информацию.
Чем опасна error-based инъекция
- Утечка данных: через ошибки можно вытащить имена таблиц, столбцов, логины, пароли, номера карт.
- Обход аутентификации: манипулируя условиями WHERE, можно войти под администратором без пароля.
- Полный контроль над БД: в некоторых конфигурациях возможны чтение/запись файлов и выполнение команд ОС.
- Скрытность: error-based атаки часто не оставляют явных следов в логах приложений, если ошибки не логируются должным образом.
Как защититься от SQL-инъекций
Главное правило — никогда не конкатенировать пользовательский ввод в SQL-запросы. Рассмотрим надёжные меры:
- Параметризованные запросы (prepared statements). Это золотой стандарт. Данные передаются отдельно от SQL-кода, и СУБД не интерпретирует их как команды.
- Хранимые процедуры. При правильной реализации также снижают риск, но не заменяют параметризацию полностью.
- Валидация и whitelist. Если параметр должен быть числом — приводите его к числу. Если строкой из фиксированного набора — проверяйте по списку.
- Экранирование. Используйте встроенные функции экранирования драйвера БД, но помните: это менее надёжно, чем prepared statements.
- Минимальные привилегии. Учётная запись приложения не должна иметь прав на DROP, FILE, доступ к information_schema без необходимости.
- Отключение вывода ошибок. Пользователь не должен видеть текст SQL-ошибок. Логируйте их на сервере, а клиенту отдавайте обобщённое сообщение.
- WAF и мониторинг. Веб-application firewall может блокировать типовые payload'ы, но не полагайтесь только на него.
- Регулярные обновления. Переходите на актуальные версии MySQL, где EXTRACTVALUE удалена, а другие потенциально опасные функции ограничены.
Проверка собственного сайта
Чтобы убедиться, что ваше приложение не уязвимо, можно использовать легальные сканеры (например, sqlmap в тестовом окружении) или провести аудит кода. Ищите места, где SQL-запросы формируются через конкатенацию строк с участием переменных из $_GET, $_POST, cookies или HTTP-заголовков. Если такие места есть — срочно переписывайте их на prepared statements.
Итог
Payload ")) OR EXTRACTVALUE(5781,CONCAT(0x7e,((SELECT (ELT(5781=5781,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции через функцию EXTRACTVALUE. Он показывает, как злоумышленник может заставить СУБД выдать данные в тексте ошибки. Понимание механики таких атак помогает разработчикам и специалистам по безопасности своевременно закрывать уязвимости. Помните: лучшая защита — параметризованные запросы и минимизация прав доступа к базе данных.
Комментарии
—Войдите, чтобы оставить комментарий