Введение в SQL-инъекции через ошибки. SQL-инъекции остаются одной из самых распространённых уязвимостей веб-приложений. Среди них выделяется класс error-based инъекций, когда злоумышленник заставляет базу данных выдать сообщение об ошибке, содержащее конфиденциальные данные. Функция EXTRACTVALUE в MySQL — один из инструментов, который может быть использован для таких атак. В этой статье мы детально разберём конкретный запрос: %" OR EXTRACTVALUE(7971,CONCAT(0x7e,((SELECT (ELT(7971=7971,1)))),0x7e))-- - и объясним, что он делает и как от него защититься.
Что такое EXTRACTVALUE и как она используется в атаках
Функция EXTRACTVALUE(XML_document, XPath_expression) в MySQL извлекает значение из XML-документа по заданному XPath-выражению. Если XPath-выражение синтаксически неверно, MySQL возвращает ошибку, которая включает переданное выражение. Это позволяет злоумышленнику внедрить в XPath подзапрос, результат которого попадёт в текст ошибки. Таким образом, атакующий может извлечь данные из базы, например, имена таблиц, столбцов или конкретные значения.
В нашем случае используется конструкция CONCAT(0x7e, ((SELECT ...)), 0x7e), где 0x7e — это тильда (~), служащая разделителем, чтобы облегчить поиск данных в сообщении об ошибке. Подзапрос (SELECT (ELT(7971=7971,1))) возвращает 1, если условие истинно (а оно всегда истинно, так как 7971=7971), иначе NULL. ELT возвращает N-й элемент из списка; здесь список состоит из одного элемента 1. Фактически это проверка, которая всегда возвращает 1. В реальной атаке вместо этого подзапроса был бы запрос к системным таблицам, например, SELECT table_name FROM information_schema.tables LIMIT 1.
Пример: если XPath-выражение содержит недопустимый символ, MySQL выдаст ошибку вида: "XPATH syntax error: '~имя_таблицы~'".
Разбор конкретного запроса
Полный запрос: %" OR EXTRACTVALUE(7971,CONCAT(0x7e,((SELECT (ELT(7971=7971,1)))),0x7e))-- -. Давайте разберём его по частям.
- %" — это, вероятно, часть оригинального запроса, где % — подстановочный знак, а " — закрывающая кавычка. Злоумышленник начинает с закрытия строки, чтобы внедрить свой код.
- OR — логический оператор, который делает условие всегда истинным, если внедрение удачно.
- EXTRACTVALUE(7971, ...) — вызов функции. Первый аргумент 7971 — это просто число, которое будет использовано как XML-документ. Поскольку это невалидный XML, функция сразу выдаст ошибку, но перед этим вычислит второй аргумент — XPath-выражение.
- CONCAT(0x7e, ((SELECT (ELT(7971=7971,1)))), 0x7e) — формирует строку: тильда + результат подзапроса + тильда. Подзапрос возвращает 1 (или в реальной атаке — данные).
- -- - — комментарий, который отсекает оставшуюся часть оригинального запроса, чтобы не вызвать синтаксическую ошибку.
В результате выполнения этого запроса MySQL выдаст ошибку, содержащую строку ~1~ (в нашем примере). В реальной атаке вместо 1 было бы, например, имя пользователя или хеш пароля.
Как это работает на практике
Предположим, уязвимый запрос выглядит так: SELECT * FROM users WHERE name = '%" OR EXTRACTVALUE(...) -- -'. После подстановки получается:
SELECT * FROM users WHERE name = '%" OR EXTRACTVALUE(7971,CONCAT(0x7e,((SELECT (ELT(7971=7971,1)))),0x7e))-- -'
MySQL выполнит:
- Закроет строку для name.
- Вычислит EXTRACTVALUE. Второй аргумент — строка '~1~'.
- Попытается извлечь XPath '~1~' из числа 7971, что невозможно, и выдаст ошибку:
XPATH syntax error: '~1~'. - Ошибка будет возвращена приложению и, если оно выводит её пользователю, злоумышленник увидит данные.
Если бы вместо ELT(7971=7971,1) стоял подзапрос к information_schema, то в ошибке отобразилось бы имя таблицы или столбца.
Последствия и защита
Успешная эксплуатация такой инъекции позволяет злоумышленнику получить доступ к произвольным данным в базе: учётные записи, персональные данные, коммерческая тайна. Это может привести к полной компрометации системы.
Для защиты необходимо:
- Использовать подготовленные выражения (prepared statements) с параметризацией запросов. Это самый надёжный способ.
- Экранировать специальные символы при невозможности использовать подготовленные выражения.
- Ограничить права пользователя базы данных, чтобы даже при инъекции нельзя было читать системные таблицы.
- Отключить вывод ошибок MySQL в продакшене — это усложнит эксплуатацию error-based инъекций.
- Регулярно обновлять СУБД и использовать WAF для фильтрации подозрительных запросов.
Важно понимать, что EXTRACTVALUE — не единственная функция, используемая в error-based инъекциях. Аналогично работают UPDATEXML, GTID_SUBSET и другие. Поэтому защита должна быть комплексной.
Заключение
Рассмотренный запрос — классический пример error-based SQL-инъекции через функцию EXTRACTVALUE. Он демонстрирует, как злоумышленник может извлечь данные, заставив базу выдать ошибку с полезной информацией. Понимание механизма таких атак помогает разработчикам и администраторам правильно выстраивать защиту. Никогда не доверяйте пользовательскому вводу и всегда используйте параметризованные запросы.
Комментарии
—Войдите, чтобы оставить комментарий