Что такое SQL-инъекция?
SQL-инъекция (SQL injection) — один из самых распространённых и опасных типов атак на веб-приложения. Злоумышленник внедряет вредоносный SQL-код в входные данные, которые приложение передаёт в базу данных без должной проверки. В результате атакующий может читать, изменять или удалять данные, а в некоторых случаях — выполнять произвольные команды на сервере.
Запрос, который мы разбираем, — это классический пример эксплуатации слепой SQL-инъекции (blind SQL injection) в СУБД MySQL. Строка %")) AND EXTRACTVALUE(6337,CONCAT(0x7e,((SELECT (ELT(6337=6337,1)))),0x7e))-- - содержит сразу несколько интересных приёмов: использование функции EXTRACTVALUE для вызова ошибки, конкатенацию через CONCAT и функцию ELT для проверки условия.
Разбор структуры запроса
Давайте разберём строку по частям, чтобы понять логику атакующего.
1. Начало: %"))
Символы %")) — это попытка закрыть существующий SQL-запрос. Знак процента часто используется в LIKE-запросах, а кавычка и две закрывающие скобки помогают «разорвать» оригинальное выражение. Например, если исходный запрос выглядел как SELECT * FROM users WHERE name LIKE '%...%', то внедрение %")) позволяет выйти за пределы строкового литерала и добавить собственные условия.
2. Логическое условие: AND EXTRACTVALUE(...)
Ключевое слово AND присоединяет дополнительное условие к исходному запросу. Если внедрённое выражение истинно, запрос выполняется так же, как и оригинальный; если ложно — результат может отличаться. Это основа слепой инъекции: атакующий наблюдает за поведением приложения (например, появляется ли ошибка или меняется ли содержимое страницы).
3. Функция EXTRACTVALUE
EXTRACTVALUE(XML_document, XPath_expression) — это функция MySQL, предназначенная для извлечения значения из XML-документа по заданному XPath-выражению. Однако она нашла неожиданное применение в SQL-инъекциях. Дело в том, что если XPath-выражение содержит недопустимые символы (например, тильду ~), функция генерирует ошибку, в тексте которой выводится переданное значение. Это позволяет атакующему извлекать данные из базы через сообщения об ошибках.
В нашем запросе EXTRACTVALUE вызывается с двумя аргументами: 6337 и результатом CONCAT. Первый аргумент — произвольное число, которое не играет роли. Второй аргумент — это XPath-выражение, которое намеренно делается некорректным, чтобы вызвать ошибку с полезной нагрузкой.
4. CONCAT и 0x7e
CONCAT объединяет строки. В данном случае она склеивает тильду (0x7e — шестнадцатеричное представление символа ~), результат подзапроса и ещё одну тильду. Тильда выбрана потому, что она недопустима в XPath и гарантированно вызовет ошибку. В сообщении об ошибке MySQL отобразит что-то вроде: XPATH syntax error: '~1~' — где между тильдами будет результат подзапроса.
5. Подзапрос: (SELECT (ELT(6337=6337,1)))
Здесь используется функция ELT(N, str1, str2, ...), которая возвращает N-ю строку из списка. Выражение 6337=6337 всегда истинно (1), поэтому ELT(1, 1) возвращает 1. Это простейший пример: атакующий проверяет, что механизм работает. В реальной атаке вместо 6337=6337 могло бы стоять условие, проверяющее, например, первый символ имени пользователя: SUBSTRING((SELECT user()),1,1)='a'. Если условие истинно, ELT вернёт 1, и в ошибке появится ~1~; если ложно — ELT вернёт NULL или другое значение, и ошибка будет иной.
6. Комментарий: -- -
Два дефиса и пробел (или дефис) — это комментарий в SQL. Всё, что идёт после -- -, игнорируется базой данных. Это нужно, чтобы «отрезать» оставшуюся часть оригинального запроса, которая могла бы вызвать синтаксическую ошибку.
Как работает атака целиком
Предположим, что уязвимый запрос выглядит так:
SELECT * FROM articles WHERE title LIKE '%ЗАПРОС%'
Подставляя нашу строку, получаем:
SELECT * FROM articles WHERE title LIKE '%%")) AND EXTRACTVALUE(6337,CONCAT(0x7e,((SELECT (ELT(6337=6337,1)))),0x7e))-- -%'
После закрытия кавычки и скобок запрос превращается в:
SELECT * FROM articles WHERE title LIKE '%%")) AND EXTRACTVALUE(6337,CONCAT(0x7e,((SELECT (ELT(6337=6337,1)))),0x7e))
База данных выполняет EXTRACTVALUE, который пытается разобрать XPath ~1~. Это вызывает ошибку, и в ответе приложения (если ошибки выводятся) появляется сообщение с результатом подзапроса. Так атакующий может извлекать данные посимвольно, задавая разные условия в ELT.
Какие уязвимости эксплуатируются
- Отсутствие параметризации запросов. Если бы приложение использовало подготовленные выражения (prepared statements), внедрение строки было бы невозможно.
- Некорректная обработка ошибок. Вывод ошибок СУБД на страницу позволяет злоумышленнику получать данные через сообщения.
- Устаревшие функции MySQL. EXTRACTVALUE и подобные (UPDATEXML) считаются устаревшими и не рекомендуются к использованию, но всё ещё встречаются в старых приложениях.
Как защититься от подобных атак
- Используйте параметризованные запросы. Это самый надёжный способ: данные передаются отдельно от SQL-кода и не могут изменить структуру запроса.
- Экранируйте специальные символы. Если параметризация невозможна, применяйте функции экранирования, предоставляемые драйвером БД.
- Отключите вывод ошибок СУБД. Пользователь не должен видеть сообщения об ошибках базы данных. Логируйте их, но не показывайте.
- Ограничьте права пользователя БД. Приложение должно работать с минимально необходимыми привилегиями.
- Регулярно обновляйте СУБД и фреймворки. Устаревшие функции могут быть удалены в новых версиях, что снизит риск.
- Используйте WAF. Веб-application firewall может блокировать известные шаблоны инъекций, но не полагайтесь только на него.
Заключение
Строка %")) AND EXTRACTVALUE(6337,CONCAT(0x7e,((SELECT (ELT(6337=6337,1)))),0x7e))-- - — это компактный, но показательный пример эксплуатации слепой SQL-инъекции в MySQL. Она демонстрирует, как злоумышленник может использовать встроенные функции для вызова ошибок и извлечения данных. Понимание таких техник помогает разработчикам и специалистам по безопасности лучше защищать свои приложения. Помните: лучшая защита — это параметризация запросов и внимательное отношение к обработке пользовательского ввода.
Комментарии
—Войдите, чтобы оставить комментарий