Что такое SQL-инъекция?
SQL-инъекция (SQL injection) — один из самых распространённых способов атаки на веб-приложения, при котором злоумышленник внедряет в пользовательский ввод специально сконструированные SQL-запросы. Цель — получить доступ к данным, изменить их или выполнить произвольные команды на сервере базы данных. Если приложение не фильтрует входные параметры, база данных может воспринять часть ввода как исполняемый код.
Существует несколько разновидностей SQL-инъекций: union-based, boolean-based, time-based и error-based. Строка, которую мы разбираем, относится к последнему типу — error-based SQL-инъекции. Она заставляет СУБД MySQL сгенерировать ошибку, содержащую результат выполнения вложенного запроса, который затем отображается в ответе сервера.
Расшифровка строки %' OR EXTRACTVALUE(7996,CONCAT(0x7e,((SELECT (ELT(7996=7996,1)))),0x7e))-- -
Давайте разберём этот запрос по частям, чтобы понять его назначение.
%'— это начало внедрения. Символ%часто используется в LIKE-запросах как шаблон, а одинарная кавычка'закрывает строковый литерал в оригинальном SQL-запросе. Таким образом, атакующий «вырывается» из контекста и добавляет свой код.OR— логический оператор, который делает условие всегда истинным или позволяет внедрить дополнительное выражение.EXTRACTVALUE(7996, CONCAT(0x7e, ((SELECT (ELT(7996=7996,1)))), 0x7e))— это функция MySQL, предназначенная для извлечения значения из XML-строки. Она принимает два аргумента: XML-документ и XPath-выражение. Если XPath-выражение некорректно, MySQL выдаёт ошибку, в тексте которой отображается переданное значение. Это и есть основа error-based инъекции.CONCAT(0x7e, ..., 0x7e)— объединяет символ~(hex-код 0x7e) с результатом подзапроса, чтобы отделить его в сообщении об ошибке.(SELECT (ELT(7996=7996,1)))— подзапрос, который возвращает число 1, если условие7996=7996истинно. ФункцияELT()возвращает N-й элемент из списка. Здесь она используется для демонстрации: в реальной атаке вместо этого подзапроса злоумышленник вставляет запрос к системным таблицам, например,SELECT table_name FROM information_schema.tables LIMIT 1.-- -— комментарий, который «отрезает» оставшуюся часть оригинального SQL-запроса, чтобы не возникло синтаксической ошибки.
Таким образом, вся конструкция заставляет базу данных выполнить подзапрос и вывести его результат в сообщении об ошибке. Это позволяет атакующему извлекать произвольные данные: имена таблиц, столбцов, логины, пароли и другую конфиденциальную информацию.
Как работает error-based SQL-инъекция в MySQL?
MySQL возвращает детализированные сообщения об ошибках, если включён режим отладки или стандартный уровень логирования. Функции EXTRACTVALUE и UPDATEXML специально используются для генерации ошибок, содержащих данные. Например, если передать в EXTRACTVALUE некорректный XPath, сервер ответит примерно так: XPATH syntax error: '~1~'. Всё, что находится между тильдами, — это результат внедрённого запроса.
Атакующий может последовательно менять условия и извлекать по одному значению за раз. Например, чтобы получить имя первой таблицы в базе, он подставит подзапрос:
EXTRACTVALUE(1, CONCAT(0x7e, (SELECT table_name FROM information_schema.tables LIMIT 0,1), 0x7e)).
Затем изменит LIMIT 0,1 на LIMIT 1,1 и так далее. Этот метод называется «пошаговым извлечением данных».
Опасность и последствия
Error-based SQL-инъекции чрезвычайно опасны, потому что позволяют полностью скомпрометировать базу данных. Злоумышленник может:
- получить доступ к персональным данным пользователей (логины, пароли, email, платёжная информация);
- изменить или удалить содержимое таблиц;
- выполнить команды администрирования СУБД, если у пользователя есть соответствующие привилегии;
- использовать базу как плацдарм для дальнейших атак на внутреннюю сеть.
Часто такие инъекции автоматизируются с помощью инструментов вроде sqlmap, что делает атаку быстрой и малозаметной.
Как защититься от SQL-инъекций?
Основной метод защиты — использование параметризованных запросов (prepared statements). В этом случае SQL-код и данные передаются раздельно, и база данных никогда не интерпретирует ввод пользователя как команды. Все современные языки программирования и фреймворки поддерживают эту технику.
Дополнительные меры:
- Валидация и фильтрация входных данных: проверяйте типы, длины, допустимые символы. Например, если ожидается число, отклоняйте всё, кроме цифр.
- Экранирование специальных символов: используйте встроенные функции СУБД или библиотеки для экранирования кавычек и других опасных символов.
- Минимизация привилегий: учётная запись, под которой работает приложение, должна иметь только необходимые права. Никогда не используйте root для веб-приложений.
- Отключение подробных сообщений об ошибках: на продакшене не показывайте пользователям текст ошибок СУБД. Это затруднит эксплуатацию error-based инъекций.
- Регулярное обновление СУБД и фреймворков: закрывайте известные уязвимости.
- Использование WAF (Web Application Firewall): современные WAF могут обнаруживать и блокировать попытки SQL-инъекций по сигнатурам.
Помните: безопасность — это процесс, а не разовое действие. Регулярно проводите аудит кода и тестирование на проникновение.
Заключение
Строка %' OR EXTRACTVALUE(7996,CONCAT(0x7e,((SELECT (ELT(7996=7996,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции, нацеленной на MySQL. Она демонстрирует, как злоумышленник может использовать функцию EXTRACTVALUE для вывода данных через сообщения об ошибках. Понимание механизмов таких атак помогает разработчикам и администраторам своевременно закрывать уязвимости и защищать свои системы.
Комментарии
—Войдите, чтобы оставить комментарий