Что такое error-based SQL-инъекция?
SQL-инъекция — один из самых распространённых способов атаки на веб-приложения. Злоумышленник внедряет вредоносный SQL-код в запрос, который приложение отправляет в базу данных. Если приложение не фильтрует входные данные, база выполняет этот код, и атакующий может получить доступ к конфиденциальной информации, изменить или удалить данные.
Error-based SQL-инъекция — это техника, при которой злоумышленник заставляет базу данных выдать сообщение об ошибке, содержащее полезные данные. Вместо того чтобы получать информацию напрямую, он извлекает её из текста ошибки. Это особенно эффективно, когда приложение не отображает результаты запроса, но выводит ошибки СУБД.
Разбор строки запроса
Рассмотрим конкретный пример: %" AND EXTRACTVALUE(3879,CONCAT(0x7e,((SELECT (ELT(3879=3879,1)))),0x7e))-- -
Эта строка — классический пример error-based SQL-инъекции для MySQL. Она предназначена для извлечения данных через сообщение об ошибке, генерируемое функцией EXTRACTVALUE.
Компоненты запроса
- %" — часть исходного параметра, которая, вероятно, закрывает строковый литерал в уязвимом запросе. Символ
%может быть частью LIKE-шаблона, а кавычка закрывает строку. - AND — логический оператор, добавляющий условие к исходному запросу.
- EXTRACTVALUE(3879, CONCAT(...)) — функция MySQL для работы с XML. Она извлекает значение из XML-документа по указанному XPath-выражению. Если XPath-выражение некорректно, функция возвращает ошибку, в тексте которой содержится переданный аргумент.
- 3879 — первый аргумент EXTRACTVALUE, который должен быть XML-документом. Здесь он не является валидным XML, что гарантирует ошибку.
- CONCAT(0x7e, ..., 0x7e) — объединяет символ
~(0x7e) с результатом подзапроса и ещё одним~. Это делается для того, чтобы отделить полезные данные в сообщении об ошибке. - SELECT (ELT(3879=3879,1)) — подзапрос, который возвращает результат функции ELT.
ELT(N, str1, str2, ...)возвращает N-ю строку из списка. Здесь условие3879=3879всегда истинно, что даёт 1, и ELT возвращает первую строку — число 1. Это простейший пример; на практике вместо1подставляется подзапрос, извлекающий данные (например, имя пользователя, версию БД и т.д.). - -- - — комментарий, который отсекает оставшуюся часть исходного SQL-запроса, чтобы не вызвать синтаксическую ошибку.
Как это работает
Когда MySQL выполняет EXTRACTVALUE с некорректным XML, он генерирует ошибку вида: XPATH syntax error: '~1~'. В этом сообщении между тильдами оказывается результат подзапроса. Атакующий может подставить вместо 1 любой другой подзапрос, например (SELECT user()), и получить имя пользователя базы данных в тексте ошибки.
Таким образом, error-based инъекция позволяет пошагово извлекать данные: имена таблиц, колонок, логины, пароли и другую чувствительную информацию.
Важно: данная техника работает только в том случае, если приложение выводит сообщения об ошибках СУБД пользователю. В противном случае атакующий может использовать blind SQL-инъекции.
Функция EXTRACTVALUE в MySQL
EXTRACTVALUE — это встроенная функция MySQL (и MariaDB), предназначенная для извлечения фрагментов XML-документа с помощью XPath. Синтаксис: EXTRACTVALUE(xml_frag, xpath_expr). Если xml_frag не является корректным XML, функция возвращает NULL и генерирует предупреждение. Однако при определённых условиях (например, в некоторых версиях) она может возвращать ошибку, содержащую переданное XPath-выражение. Это и используется для инъекций.
Начиная с MySQL 5.7, поведение функции было изменено: она стала возвращать NULL вместо ошибки, что усложнило эксплуатацию. Тем не менее, на старых версиях уязвимость широко распространена.
Функция ELT
ELT (English: Extract, List, Transform) — это функция MySQL, которая возвращает N-й элемент из списка строк. Синтаксис: ELT(N, str1, str2, ...). Если N=1, возвращается str1, если N=2 — str2 и т.д. В нашем примере ELT(3879=3879,1) возвращает 1, так как условие истинно. Это простой способ вернуть константу, но в реальных атаках вместо неё подставляют подзапросы, извлекающие данные.
Как защититься от error-based SQL-инъекций
Основные меры защиты:
- Использование подготовленных выражений (prepared statements) с параметризацией запросов. Это самый надёжный способ, так как данные не интерпретируются как SQL-код.
- Экранирование специальных символов с помощью функций вроде
mysqli_real_escape_string. - Отключение вывода ошибок СУБД на продакшене. Ошибки должны логироваться, но не показываться пользователю.
- Применение WAF (Web Application Firewall) для фильтрации подозрительных запросов.
- Регулярное обновление СУБД до версий, где подобные функции не вызывают ошибок с полезной нагрузкой.
- Принцип наименьших привилегий для учётной записи базы данных, используемой приложением.
Заключение
Строка %" AND EXTRACTVALUE(3879,CONCAT(0x7e,((SELECT (ELT(3879=3879,1)))),0x7e))-- - — это типичный пример error-based SQL-инъекции, эксплуатирующей особенности функций MySQL. Понимание таких атак помогает разработчикам и специалистам по безопасности лучше защищать свои приложения. Никогда не доверяйте пользовательскому вводу и всегда используйте параметризованные запросы.
Комментарии
—Войдите, чтобы оставить комментарий