Что такое error-based SQL-инъекция?
SQL-инъекция — один из самых распространённых способов атаки на веб-приложения, при котором злоумышленник внедряет вредоносный SQL-код в запросы к базе данных. Существует несколько разновидностей таких атак, и одна из самых изощрённых — error-based SQL-инъекция (инъекция на основе ошибок). В этом случае атакующий заставляет СУБД выдать сообщение об ошибке, которое содержит конфиденциальные данные, например, имена таблиц, логины или хеши паролей.
Особое место среди таких атак занимает использование функции EXTRACTVALUE в MySQL. Эта функция предназначена для работы с XML-документами, но при неправильной обработке пользовательского ввода она становится мощным инструментом для извлечения данных через ошибки.
Синтаксис и назначение EXTRACTVALUE
Функция EXTRACTVALUE(XML_document, XPath_expression) возвращает текст из XML-документа, соответствующий указанному XPath-выражению. Например, запрос:
SELECT EXTRACTVALUE('<a><b>Текст</b></a>', '/a/b');
вернёт строку «Текст». Однако если XPath-выражение содержит синтаксическую ошибку, MySQL сгенерирует сообщение об ошибке, в котором будет указана часть переданного выражения. Именно это свойство и используют злоумышленники.
Разбор конкретного запроса
Рассмотрим строку, которая часто встречается в отчётах об уязвимостях и на форумах по безопасности:
%"))) AND EXTRACTVALUE(7954,CONCAT(0x7e,((SELECT (ELT(7954=7954,1)))),0x7e))-- -
Это классический пример error-based SQL-инъекции для MySQL. Давайте разберём его по частям.
1. Начало: %")))
Символы %"))) — это попытка «закрыть» исходный SQL-запрос, который, вероятно, выглядел как:
SELECT * FROM users WHERE name = '%"))) ...';
Атакующий добавляет символы, чтобы разорвать строковый литерал и внедрить собственный код. Процент (%) и кавычки помогают обойти простые фильтры.
2. Логическое условие AND
Оператор AND присоединяет вредоносное выражение к оригинальному запросу. Если исходный запрос возвращал какие-то данные, то после добавления AND результат будет зависеть от истинности внедрённого условия.
3. Функция EXTRACTVALUE(7954, CONCAT(...))
Первый аргумент — число 7954. Это не XML-документ, а просто число, которое MySQL попытается интерпретировать как XML. Второй аргумент — результат функции CONCAT, который формирует строку, начинающуюся и заканчивающуюся символом ~ (код 0x7e). Внутри — подзапрос (SELECT (ELT(7954=7954,1))).
4. Подзапрос ELT(7954=7954,1)
Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 7954=7954 — это всегда истина (1), поэтому ELT(1,1) вернёт 1. Казалось бы, бессмысленно, но это лишь демонстрация. В реальной атаке вместо 1 могло бы быть имя таблицы, версия СУБД или другой полезный данные, полученные через подзапрос.
5. Завершение: -- -
Два дефиса и пробел (или дефис) — это комментарий в SQL, который «отрезает» оставшуюся часть оригинального запроса, чтобы синтаксис был корректным.
Как это работает на практике
Когда MySQL выполняет EXTRACTVALUE(7954, CONCAT(0x7e, (SELECT ...), 0x7e)), он пытается разобрать второй аргумент как XPath. Строка, начинающаяся с ~, не является допустимым XPath-выражением, поэтому СУБД выдаёт ошибку вида:
XPATH syntax error: '~1~'
В этом сообщении содержится результат подзапроса — в нашем случае «1». Если вместо ELT(7954=7954,1) подставить, например, (SELECT version()), то в ошибке появится версия MySQL. Аналогично можно извлечь имена таблиц, колонок и даже хеши паролей.
Почему это опасно?
Error-based инъекции через EXTRACTVALUE позволяют атакующему:
- Получить информацию о структуре базы данных (имена таблиц и столбцов).
- Извлечь учётные данные пользователей, включая логины и пароли (в виде хешей).
- Читать произвольные данные из таблиц, к которым у приложения есть доступ.
- В некоторых случаях — выполнять команды на сервере, если СУБД скомпрометирована.
Особенность таких атак в том, что они не требуют вывода данных на страницу — достаточно, чтобы сообщение об ошибке отображалось пользователю или сохранялось в логах, доступных злоумышленнику.
Методы защиты
Чтобы предотвратить SQL-инъекции, включая error-based через EXTRACTVALUE, необходимо применять комплекс мер:
- Использование подготовленных выражений (prepared statements). Это самый надёжный способ: параметры запроса передаются отдельно от SQL-кода, и внедрение становится невозможным.
- Экранирование специальных символов. Если по каким-то причинам prepared statements недоступны, необходимо тщательно фильтровать пользовательский ввод, особенно кавычки, обратные слэши и символы комментариев.
- Отключение вывода ошибок СУБД в production. Сообщения об ошибках не должны показываться пользователям. Логи ошибок следует хранить в защищённом месте.
- Принцип минимальных привилегий. Учётная запись, от имени которой работает приложение, должна иметь только необходимые права. Например, не должна иметь доступ к системным таблицам.
- Регулярное обновление СУБД. В новых версиях MySQL некоторые функции могут быть исправлены или удалены, что снижает риск.
- Использование WAF (Web Application Firewall). Современные WAF умеют распознавать шаблоны error-based инъекций, включая конструкции с
EXTRACTVALUE.
Заключение
Запрос %"))) AND EXTRACTVALUE(7954,CONCAT(0x7e,((SELECT (ELT(7954=7954,1)))),0x7e))-- - — это учебный пример эксплуатации уязвимости error-based SQL-инъекции в MySQL. Он демонстрирует, как через функцию EXTRACTVALUE и намеренно вызванную ошибку XPath можно извлечь данные из базы. Понимание таких техник необходимо разработчикам и специалистам по безопасности для построения надёжной защиты веб-приложений.
Помните: безопасность — это процесс, а не одноразовое действие. Используйте параметризованные запросы, ограничивайте права доступа и следите за обновлениями.
Комментарии
—Войдите, чтобы оставить комментарий