Что это за строка с EXTRACTVALUE?

Если вы увидели в логах веб-сервера или в параметрах URL строку вида %")))) AND EXTRACTVALUE(8067,CONCAT(0x7e,((SELECT (ELT(8067=8067,1)))),0x7e))-- -, знайте: перед вами классический пример error-based SQL-инъекции. Это попытка злоумышленника заставить базу данных вернуть сообщение об ошибке, содержащее полезную для атакующего информацию. Подобные конструкции часто встречаются в автоматизированных сканерах уязвимостей, которые проверяют сайты на наличие дыр в защите.

В данной статье мы подробно разберём, из чего состоит этот запрос, как он работает, какие цели преследует и, главное, как защитить свой сайт от подобных атак.

Разбор конструкции по частям

Начнём с начала строки. Символы %")))) — это попытка закрыть ранее открытые кавычки и скобки в уязвимом SQL-запросе. Проценты и кавычки часто используются для обхода простых фильтров. Далее идёт ключевое слово AND, которое добавляет условие к исходному запросу.

Основная часть — функция EXTRACTVALUE(8067,CONCAT(0x7e,((SELECT (ELT(8067=8067,1)))),0x7e)). EXTRACTVALUE — это функция MySQL (и MariaDB), предназначенная для извлечения значения из XML-документа по XPath-выражению. Она принимает два аргумента: XMLType-экземпляр и XPath-выражение. Если XPath-выражение некорректно или возвращает недопустимый результат, функция генерирует ошибку, в тексте которой может отображаться переданное значение.

Второй аргумент — CONCAT(0x7e,((SELECT (ELT(8067=8067,1)))),0x7e). CONCAT объединяет строки. 0x7e — это шестнадцатеричное представление символа тильды (~). Он используется как маркер, чтобы в сообщении об ошибке легко было найти внедрённые данные. SELECT (ELT(8067=8067,1)) — это подзапрос, который возвращает результат функции ELT. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 8067=8067 — всегда истинное выражение, которое в числовом контексте даёт 1, поэтому ELT(1, 1) вернёт строку '1'.

Завершают конструкцию символы -- - — это комментарий в SQL, который отсекает оставшуюся часть исходного запроса, чтобы не возникло синтаксической ошибки.

Как работает error-based инъекция

Цель атакующего — заставить базу данных выдать сообщение об ошибке, содержащее результат выполнения подзапроса. В данном примере подзапрос возвращает всего лишь '1', но это демонстрация уязвимости. В реальной атаке вместо ELT(8067=8067,1) может стоять, например, SELECT version() или SELECT password FROM users LIMIT 1. Тогда в тексте ошибки EXTRACTVALUE появится версия СУБД или хеш пароля.

Механизм таков: MySQL пытается выполнить XPath-запрос, который содержит символ тильды и внедрённые данные. Поскольку такой XPath синтаксически неверен, СУБД возвращает ошибку вида XPATH syntax error: '~5.7.33~'. Атакующий читает эту ошибку и получает нужную информацию.

Error-based SQL-инъекции — один из самых быстрых способов извлечения данных, так как не требуют слепого перебора. Достаточно одной уязвимости, чтобы выкачать всю базу.

Почему это опасно?

Успешная эксплуатация error-based инъекции открывает злоумышленнику доступ к содержимому базы данных. В зависимости от привилегий пользователя, от имени которого работает веб-приложение, он может:

  • получить список таблиц и колонок;
  • извлечь логины, пароли, персональные данные пользователей;
  • изменить или удалить информацию;
  • в некоторых случаях выполнить произвольные команды на сервере.

Особенно опасны такие атаки для сайтов, где ввод пользователя попадает в SQL-запрос без должной обработки. Часто это формы авторизации, поиска, фильтры товаров.

Как защититься от SQL-инъекций

Главное правило — никогда не доверять пользовательскому вводу. Все данные, приходящие от клиента, должны проходить валидацию и экранирование. Вот основные меры защиты:

  1. Использование подготовленных выражений (prepared statements). Это самый надёжный способ. Параметры передаются отдельно от SQL-кода, и СУБД не интерпретирует их как часть запроса.
  2. Применение ORM. Современные фреймворки (Django, Laravel, Hibernate) автоматически используют параметризацию, если разработчик не пишет сырые запросы вручную.
  3. Экранирование специальных символов. Если по каким-то причинам нельзя использовать подготовленные выражения, нужно применять функции экранирования, например mysqli_real_escape_string в PHP.
  4. Ограничение привилегий пользователя БД. Веб-приложение должно работать от имени пользователя с минимально необходимыми правами. Не давайте ему доступ к системным таблицам и возможность выполнять DROP или FILE.
  5. Регулярное обновление СУБД и фреймворков. Иногда уязвимости возникают из-за ошибок в самом ПО.
  6. Использование WAF (Web Application Firewall). Специализированные решения могут блокировать подозрительные запросы, содержащие характерные сигнатуры SQL-инъекций.

Также рекомендуется вести логирование всех запросов к базе данных и анализировать их на предмет аномалий. Если вы обнаружили в логах строку, подобную описанной, это повод немедленно проверить код приложения на наличие уязвимостей.

Что делать, если вы нашли такой запрос в логах?

Прежде всего, не паникуйте. Возможно, это просто сканер, который не смог ничего навредить. Но игнорировать нельзя. Проверьте:

  • не было ли успешных попыток инъекции с других IP;
  • есть ли в приложении места, где пользовательский ввод попадает в SQL без параметризации;
  • не скомпрометированы ли учётные записи пользователей.

Если вы не уверены в безопасности своего кода, лучше обратиться к специалистам по информационной безопасности и провести аудит.

Заключение

Строка %")))) AND EXTRACTVALUE(8067,CONCAT(0x7e,((SELECT (ELT(8067=8067,1)))),0x7e))-- - — это не случайный набор символов, а целенаправленная попытка проэксплуатировать уязвимость SQL-инъекции. Понимание того, как работают такие атаки, помогает разработчикам писать более безопасный код, а администраторам — своевременно реагировать на инциденты. Помните: лучшая защита — это параметризованные запросы и внимательное отношение к безопасности на всех этапах разработки.

Источники