Введение
Встречая в логах веб-сервера или в поле ввода подобную строку: ) AND EXTRACTVALUE(6898,CONCAT(0x7e,((SELECT (ELT(6898=6898,1)))),0x7e))-- -, многие задаются вопросом: что это и какова её цель? Это классический пример SQL-инъекции, нацеленной на извлечение информации из базы данных через генерацию ошибок. В данной статье мы подробно разберём, как работает этот запрос, какие функции MySQL задействованы и как защититься от подобных атак.
Что такое SQL-инъекция?
SQL-инъекция (SQL injection) — один из самых распространённых способов взлома веб-приложений, при котором злоумышленник внедряет произвольный SQL-код в запрос к базе данных. Это становится возможным, когда приложение не проверяет должным образом пользовательский ввод и передаёт его напрямую в SQL-запрос. Успешная инъекция может привести к утечке конфиденциальных данных, модификации или удалению информации, а в некоторых случаях — к полному контролю над сервером.
Существует несколько типов SQL-инъекций: UNION-based, error-based, blind (boolean и time-based) и другие. Рассматриваемая строка относится к error-based инъекциям, когда злоумышленник заставляет базу данных выдать сообщение об ошибке, содержащее нужные данные.
Разбор строки инъекции
Давайте разберём запрос по частям:
) AND EXTRACTVALUE(6898,CONCAT(0x7e,((SELECT (ELT(6898=6898,1)))),0x7e))-- -
Начнём с конца: -- - — это комментарий в SQL, который отсекает всё, что идёт после инъекции, чтобы исходный запрос остался синтаксически корректным. Символ ) в начале закрывает скобку, которая, вероятно, была открыта в оригинальном запросе.
Далее идёт AND EXTRACTVALUE(...). Функция EXTRACTVALUE(XML_document, XPath_expression) в MySQL извлекает значение из XML-документа по заданному XPath-выражению. Если XPath-выражение содержит недопустимые символы, MySQL генерирует ошибку, в тексте которой отображается переданное выражение. Это и используется для извлечения данных.
Второй аргумент — CONCAT(0x7e, ((SELECT (ELT(6898=6898,1)))), 0x7e). Функция CONCAT объединяет строки. 0x7e — это шестнадцатеричное представление символа тильды (~). Тильда используется как разделитель, чтобы облегчить поиск выводимых данных в сообщении об ошибке.
Внутри CONCAT находится подзапрос SELECT (ELT(6898=6898,1)). Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае ELT(6898=6898, 1) — условие 6898=6898 истинно, что в MySQL эквивалентно 1, поэтому ELT(1, 1) вернёт строку '1'. Это простейший пример; на практике вместо '1' подставляются имена таблиц, колонок или другие данные, которые нужно извлечь.
Таким образом, при выполнении запроса MySQL попытается извлечь значение из XML, но поскольку XPath-выражение содержит символ ~ (или другие недопустимые символы), возникнет ошибка вида: XPATH syntax error: '~1~'. В этом сообщении злоумышленник увидит результат выполнения подзапроса — в данном случае '1'.
Зачем это нужно злоумышленнику?
Цель error-based инъекций — получить данные из базы, даже если приложение не выводит результаты запроса напрямую. Ошибки часто отображаются в браузере или записываются в логи, к которым у атакующего может быть доступ. Используя EXTRACTVALUE или аналогичные функции (UPDATEXML, GTID_SUBSET и др.), можно посимвольно извлекать имена таблиц, колонок, логины и пароли пользователей.
В приведённом примере подзапрос возвращает '1', но если заменить его на (SELECT password FROM users LIMIT 1), то в ошибке появится пароль первого пользователя. Именно так работают автоматизированные инструменты, например, sqlmap.
Другие варианты использования EXTRACTVALUE
Помимо ELT, злоумышленники часто комбинируют EXTRACTVALUE с CONCAT и SELECT для извлечения произвольных данных. Например:
AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))
Этот запрос выведет версию MySQL в сообщении об ошибке. Аналогично можно получить имя текущей базы данных (database()), пользователя (user()) и многое другое.
Как защититься от SQL-инъекций?
Основной метод защиты — использование параметризованных запросов (prepared statements). В этом случае пользовательский ввод передаётся отдельно от SQL-кода, и база данных не интерпретирует его как часть запроса. Вот несколько ключевых рекомендаций:
- Параметризация запросов: Всегда используйте подготовленные выражения с плейсхолдерами для любых данных, поступающих от пользователя.
- Валидация ввода: Проверяйте типы данных, длину, допустимые символы. Например, если ожидается число, убедитесь, что ввод является числом.
- Экранирование: Если параметризация невозможна, применяйте функции экранирования, предоставляемые драйвером БД (например,
mysqli_real_escape_stringв PHP). - Минимальные привилегии: Учётная запись, используемая приложением для подключения к БД, должна иметь только необходимые права. Не используйте root.
- Регулярные обновления: Следите за обновлениями СУБД и фреймворков, чтобы закрыть известные уязвимости.
- WAF: Веб-приложения могут быть защищены с помощью Web Application Firewall, который блокирует подозрительные запросы.
Заключение
Строка AND EXTRACTVALUE(6898,CONCAT(0x7e,((SELECT (ELT(6898=6898,1)))),0x7e))-- - — это типичный пример error-based SQL-инъекции, использующей особенности функций MySQL для извлечения данных через сообщения об ошибках. Понимание механизмов таких атак помогает разработчикам и администраторам лучше защищать свои системы. Всегда применяйте параметризованные запросы и следуйте лучшим практикам безопасности, чтобы предотвратить подобные вторжения.
Комментарии
—Войдите, чтобы оставить комментарий