Что такое error-based SQL-инъекция?
SQL-инъекция — это один из самых распространённых способов атаки на веб-приложения, при котором злоумышленник внедряет в запрос к базе данных произвольный SQL-код. Существует несколько разновидностей таких атак, и одна из самых изощрённых — error-based SQL-инъекция (инъекция на основе ошибок). В этом случае хакер заставляет СУБД сгенерировать сообщение об ошибке, которое содержит полезные данные, извлечённые из базы.
Строка, которую мы разбираем, — %') OR EXTRACTVALUE(7604,CONCAT(0x7e,((SELECT (ELT(7604=7604,1)))),0x7e))-- - — является классическим примером такой атаки для СУБД MySQL. Давайте детально разберём каждый элемент этого запроса.
Разбор структуры инъекции
Начнём с начала строки. Символы %') — это попытка закрыть ранее открытую кавычку и скобку в уязвимом параметре. Знак % часто используется как часть URL-кодирования, но в данном контексте это просто часть полезной нагрузки. Далее следует OR — логический оператор, который делает условие всегда истинным (если правая часть вернёт истину) или позволяет внедрить дополнительное выражение.
Ключевой элемент — функция EXTRACTVALUE(7604, CONCAT(0x7e, ...)). EXTRACTVALUE — это встроенная функция MySQL, предназначенная для извлечения значения из XML-документа по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_document, XPath_expression). Если XPath-выражение некорректно, MySQL выдаёт ошибку, в тексте которой отображается переданный фрагмент. Именно это и эксплуатирует атакующий.
Первый аргумент 7604 — это просто число, которое не является валидным XML-документом, что уже провоцирует ошибку. Но главное — второй аргумент, где через CONCAT собирается строка. 0x7e — это шестнадцатеричное представление символа ~ (тильда). Тильда используется как маркер, чтобы легко найти извлечённые данные в сообщении об ошибке.
Функция ELT и условие 7604=7604
Внутри CONCAT находится подзапрос: (SELECT (ELT(7604=7604,1))). Функция ELT возвращает N-й элемент из списка строк. Синтаксис: ELT(N, str1, str2, ...). В данном случае N — это результат выражения 7604=7604, которое всегда истинно и возвращает 1. Следовательно, ELT(1, 1) вернёт строку '1'. Это простейший пример; на практике вместо 1 подставляются имена таблиц, колонок или другие данные, извлекаемые из базы.
Таким образом, CONCAT(0x7e, '1', 0x7e) создаст строку ~1~. Затем EXTRACTVALUE попытается интерпретировать её как XPath, что вызовет ошибку вида: XPATH syntax error: '~1~'. В этом сообщении и будет содержаться искомая информация.
Зачем нужен комментарий -- -
В конце строки стоит -- -. Двойной дефис в SQL обозначает начало комментария, который игнорирует всё, что идёт после него в исходном запросе. Пробел после -- обязателен в некоторых СУБД, а дополнительный дефис часто добавляют для обхода фильтров. Это позволяет атакующему «отрезать» остаток оригинального запроса, чтобы синтаксис оставался корректным.
Как это работает на практике
Предположим, уязвимый запрос выглядит так:
SELECT * FROM users WHERE name = '$input';
Если в $input передать нашу строку, то после подстановки получится:
SELECT * FROM users WHERE name = '%') OR EXTRACTVALUE(7604,CONCAT(0x7e,((SELECT (ELT(7604=7604,1)))),0x7e))-- -';
База данных выполнит запрос, и если условие OR истинно, вернёт все строки таблицы. Но главное — при вычислении EXTRACTVALUE возникнет ошибка, которая будет выведена в ответе приложения, если включён режим отображения ошибок. В нашем случае это будет XPATH syntax error: '~1~'. Заменив 1 на подзапрос, например (SELECT version()), атакующий получит версию MySQL в тексте ошибки.
Какие данные можно извлечь
С помощью этой техники злоумышленник может получить практически любую информацию из базы:
- версию СУБД;
- имя текущей базы данных;
- список таблиц и колонок;
- учётные данные пользователей (логины, хеши паролей);
- любые другие данные, доступные в рамках прав уязвимого приложения.
Ограничение лишь в том, что длина выводимой строки в сообщении об ошибке обычно не превышает 32 символа, поэтому данные извлекают по частям с помощью SUBSTRING или LIMIT.
Как защититься от error-based SQL-инъекций
Основной метод защиты — использование параметризованных запросов (prepared statements). В этом случае данные никогда не смешиваются с SQL-кодом, и инъекция становится невозможной. Дополнительные меры:
- Отключить вывод ошибок СУБД в production-окружении.
- Использовать ORM или библиотеки, автоматически экранирующие входные данные.
- Проводить регулярный аудит кода и пентесты.
- Применять принцип наименьших привилегий для учётной записи базы данных.
- Установить WAF (Web Application Firewall) для фильтрации подозрительных запросов.
Важно понимать, что EXTRACTVALUE — не единственная функция, используемая в error-based атаках. Аналогично применяются UPDATEXML, GTID_SUBSET и другие. Однако EXTRACTVALUE остаётся популярной из-за простоты и надёжности.
Заключение
Строка %') OR EXTRACTVALUE(7604,CONCAT(0x7e,((SELECT (ELT(7604=7604,1)))),0x7e))-- - — это учебный пример эксплуатации error-based SQL-инъекции в MySQL. Она демонстрирует, как через намеренно вызванную ошибку XPath можно извлечь данные. Понимание таких атак необходимо разработчикам и специалистам по безопасности для эффективной защиты веб-приложений.
Комментарии
—Войдите, чтобы оставить комментарий