Что такое SQL-инъекция через ExtractValue?
SQL-инъекция — один из самых распространённых способов атаки на веб-приложения, при котором злоумышленник внедряет вредоносный SQL-код в запросы к базе данных. Существует несколько разновидностей таких атак, и одна из них — error-based SQL-инъекция, основанная на вызове ошибок базы данных, содержащих полезную для атакующего информацию. В MySQL для этого часто используется функция ExtractValue().
Функция ExtractValue() предназначена для извлечения значения из XML-документа по заданному XPath-выражению. Однако при передаче некорректного XPath-выражения MySQL генерирует сообщение об ошибке, в которое попадает часть переданной строки. Это позволяет злоумышленнику «вытащить» данные из базы, подставив их в XPath и вызвав ошибку, которая будет отображена на странице.
Разбор конкретного запроса
Рассмотрим запрос, который часто встречается в отчётах об уязвимостях и на форумах по информационной безопасности:
%" OR EXTRACTVALUE(1877,CONCAT(0x7e,((SELECT (ELT(1877=1877,1)))),0x7e))-- -
Этот запрос представляет собой попытку эксплуатации error-based SQL-инъекции. Разберём его по частям.
1. Начало: %"
Символ % в SQL часто используется как шаблон для поиска (например, в операторе LIKE). Кавычка " закрывает строковый литерал в исходном запросе приложения. Таким образом, злоумышленник пытается «разорвать» изначальный SQL-запрос и добавить свой код.
2. OR EXTRACTVALUE(...)
Оператор OR используется для того, чтобы внедрённое условие выполнилось, даже если первая часть запроса ложна. Далее вызывается функция EXTRACTVALUE() с двумя аргументами:
- Первый аргумент —
1877. Это произвольное число, которое в данном случае не играет роли, так как XML-документ не передаётся. Функция ожидает XML-строку, но получает число, что уже может вызвать ошибку. - Второй аргумент —
CONCAT(0x7e,((SELECT (ELT(1877=1877,1)))),0x7e). Здесь0x7e— это шестнадцатеричное представление символа~(тильда).CONCATобъединяет тильду, результат подзапроса и ещё одну тильду.
3. Подзапрос SELECT (ELT(1877=1877,1))
ELT() — это функция MySQL, которая возвращает N-й элемент из списка. Синтаксис: ELT(N, str1, str2, ...). В нашем случае N — это выражение 1877=1877, которое всегда истинно и в числовом контексте равно 1. Список состоит из одного элемента — 1. Таким образом, ELT(1, 1) вернёт 1. Подзапрос SELECT (ELT(1877=1877,1)) вернёт строку '1'.
Фактически это простейший пример: злоумышленник мог бы написать SELECT 1, но использование ELT и сравнения 1877=1877 — это демонстрация техники, которая в реальной атаке заменяется на извлечение данных, например, SELECT version() или SELECT password FROM users LIMIT 1.
4. Формирование XPath и ошибка
Второй аргумент EXTRACTVALUE после вычисления CONCAT будет выглядеть как ~1~. Функция EXTRACTVALUE попытается интерпретировать эту строку как XPath-выражение. Строка ~1~ не является корректным XPath (тильда недопустима в начале выражения), поэтому MySQL сгенерирует ошибку вида:
ERROR 1105 (HY000): XPATH syntax error: '~1~'
В сообщении об ошибке отобразится переданная строка, содержащая результат подзапроса. Если бы вместо 1 был, например, хеш пароля, он бы попал в текст ошибки и стал доступен атакующему.
5. Комментарий -- -
Двойной дефис -- в SQL обозначает начало комментария. Пробел после него и дефис в конце (-- -) используются для обхода возможных фильтров и гарантируют, что остальная часть исходного запроса будет проигнорирована.
Зачем это нужно злоумышленнику?
Основная цель — получить доступ к данным, которые не должны быть видны. С помощью error-based инъекций можно извлекать:
- версию СУБД;
- имена таблиц и колонок;
- логины и пароли пользователей;
- другую конфиденциальную информацию.
В приведённом примере извлекается просто число 1, но это лишь демонстрация уязвимости. В реальной атаке вместо 1 подставляются подзапросы, возвращающие ценные данные.
Как защититься от таких атак?
Чтобы предотвратить SQL-инъекции, необходимо следовать следующим рекомендациям:
- Использовать подготовленные выражения (prepared statements). Это самый надёжный способ, при котором SQL-код и данные передаются раздельно, и СУБД не интерпретирует ввод пользователя как часть запроса.
- Применять хранимые процедуры. Если они написаны корректно, это также снижает риск инъекций.
- Экранировать специальные символы. Но этот метод менее надёжен, чем подготовленные выражения.
- Ограничить права пользователя базы данных. Веб-приложение должно работать с БД от имени пользователя с минимально необходимыми привилегиями.
- Регулярно обновлять СУБД и фреймворки. В новых версиях часто исправляются известные уязвимости.
- Использовать WAF (Web Application Firewall). Он может блокировать подозрительные запросы, но не должен быть единственной мерой защиты.
Заключение
Запрос %" OR EXTRACTVALUE(1877,CONCAT(0x7e,((SELECT (ELT(1877=1877,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции через функцию EXTRACTVALUE в MySQL. Он показывает, как злоумышленник может заставить базу данных выдать ошибку, содержащую полезные данные. Понимание таких техник необходимо для разработки безопасных приложений и защиты информации.
Помните: безопасность — это процесс, а не одноразовое действие. Регулярный аудит кода и тестирование на проникновение помогают выявлять уязвимости до того, как ими воспользуются злоумышленники.
Комментарии
—Войдите, чтобы оставить комментарий