Что такое SQL-инъекция через ExtractValue?
SQL-инъекция — один из самых распространённых способов атаки на веб-приложения, при котором злоумышленник внедряет вредоносный SQL-код в запросы к базе данных. Одной из разновидностей является error-based SQL-инъекция, при которой атакующий извлекает данные, вызывая ошибки в СУБД. Функция ExtractValue в MySQL часто используется для таких атак, поскольку она позволяет получить содержимое базы в тексте сообщения об ошибке.
В этой статье мы детально разберём конкретную полезную нагрузку: ')) OR EXTRACTVALUE(3296,CONCAT(0x7e,((SELECT (ELT(3296=3296,1)))),0x7e))-- -. Вы узнаете, как она работает, зачем нужны отдельные её части и как защитить своё приложение от подобных атак.
Разбор полезной нагрузки
Рассмотрим запрос по частям:
'))— закрывает существующие скобки и кавычки в уязвимом SQL-запросе, чтобы внедрить свой код.OR— логический оператор, который делает условие всегда истинным, если правая часть вернёт ошибку или истину.EXTRACTVALUE(3296, CONCAT(0x7e, ((SELECT (ELT(3296=3296,1)))), 0x7e))— вызов функции ExtractValue с двумя аргументами: первый — произвольное число (3296), второй — XPath-выражение, которое формируется динамически.-- -— комментарий, который отсекает оставшуюся часть оригинального запроса.
Функция ExtractValue
ExtractValue — это встроенная функция MySQL, предназначенная для извлечения значения из XML-строки по заданному XPath-выражению. Синтаксис: ExtractValue(xml_frag, xpath_expr). Если XPath-выражение некорректно, MySQL генерирует ошибку с текстом, содержащим переданное выражение. Именно это свойство и эксплуатируется в error-based инъекциях: злоумышленник может поместить в XPath результат подзапроса, и он отобразится в сообщении об ошибке.
Конкатенация и маркеры
В нашем примере используется CONCAT(0x7e, ((SELECT (ELT(3296=3296,1)))), 0x7e). 0x7e — это шестнадцатеричное представление символа тильды (~). Тильды служат маркерами, чтобы легко найти извлечённые данные в тексте ошибки. Внутри конкатенации выполняется подзапрос SELECT (ELT(3296=3296,1)).
ELT — функция, возвращающая N-й элемент из списка. Здесь ELT(3296=3296,1) вернёт 1, так как условие 3296=3296 истинно (равно 1). Это простейший пример; на практике вместо ELT могут быть подзапросы к системным таблицам, например SELECT user() или SELECT database().
Итоговое выражение
Таким образом, ExtractValue получает XPath-строку вида ~1~, которая не является валидным XPath. MySQL выдаёт ошибку: XPATH syntax error: '~1~'. В реальной атаке вместо 1 будет, например, имя базы данных или хеш пароля.
Пример работы в уязвимом запросе
Предположим, что на сервере выполняется следующий SQL-запрос, где $id берётся из параметра URL:
SELECT * FROM articles WHERE id = ('$id')
Если передать ')) OR EXTRACTVALUE(3296,CONCAT(0x7e,((SELECT (ELT(3296=3296,1)))),0x7e))-- -, то после подстановки получится:
SELECT * FROM articles WHERE id = ('') OR EXTRACTVALUE(3296,CONCAT(0x7e,((SELECT (ELT(3296=3296,1)))),0x7e))-- -')
Часть запроса после -- - игнорируется. Условие OR заставляет MySQL выполнить функцию ExtractValue, которая вызовет ошибку с текстом XPATH syntax error: '~1~'. Атакующий увидит этот текст на странице (если ошибки выводятся) и поймёт, что инъекция работает.
Зачем это нужно злоумышленнику?
Основная цель — извлечение данных из базы. Меняя подзапрос внутри CONCAT, можно получить:
- версию СУБД:
SELECT version(); - имя текущей базы:
SELECT database(); - список таблиц:
SELECT table_name FROM information_schema.tables; - данные пользователей: логины, пароли, email.
Функция ExtractValue позволяет обойти ограничения, связанные с выводом данных, и получить их через сообщения об ошибках. Это особенно опасно, когда приложение не фильтрует ввод и отображает ошибки MySQL.
Как защититься от error-based SQL-инъекций?
Чтобы предотвратить подобные атаки, следуйте этим рекомендациям:
- Используйте подготовленные выражения (prepared statements). Это самый надёжный способ, при котором параметры запроса передаются отдельно от SQL-кода и не могут изменить его структуру.
- Экранируйте специальные символы. Если prepared statements недоступны, применяйте функции экранирования, например
mysqli_real_escape_stringв PHP. - Отключите вывод ошибок СУБД на продакшене. Сообщения об ошибках не должны попадать в браузер пользователя — это лишает атакующего обратной связи.
- Ограничьте права пользователя БД. Не используйте учётную запись с полными правами для веб-приложения.
- Регулярно обновляйте СУБД и фреймворки. В новых версиях часто исправляются известные уязвимости.
- Используйте WAF (Web Application Firewall). Он может блокировать подозрительные запросы, содержащие функции вроде ExtractValue.
Заключение
Полезная нагрузка ')) OR EXTRACTVALUE(3296,CONCAT(0x7e,((SELECT (ELT(3296=3296,1)))),0x7e))-- - — классический пример error-based SQL-инъекции через функцию ExtractValue в MySQL. Она позволяет атакующему извлекать произвольные данные из базы, вызывая ошибки с внедрённым содержимым. Понимание механики таких атак помогает разработчикам и администраторам лучше защищать свои приложения. Главный совет: никогда не доверяйте пользовательскому вводу и всегда используйте параметризованные запросы.
Комментарии
—Войдите, чтобы оставить комментарий