Введение

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

Что такое SQL-инъекция?

SQL-инъекция (SQL injection) — один из самых распространённых способов взлома веб-приложений, при котором злоумышленник внедряет произвольный SQL-код в запрос к базе данных. Это становится возможным, когда приложение небезопасно обрабатывает пользовательский ввод, например, не экранирует специальные символы или не использует параметризованные запросы. Цель инъекции — получить доступ к конфиденциальным данным, изменить или удалить информацию, а иногда и выполнить команды на сервере.

Существует несколько типов SQL-инъекций: классическая (union-based), слепая (blind), временная (time-based) и основанная на ошибках (error-based). Рассматриваемый запрос относится именно к последнему типу — error-based SQL injection.

Разбор вредоносного запроса

Давайте детально разберём строку %")))) AND EXTRACTVALUE(4742,CONCAT(0x7e,((SELECT (ELT(4742=4742,1)))),0x7e))-- -.

  • %")))) — это часть, которая, вероятно, закрывает предыдущие кавычки и скобки в исходном запросе, чтобы внедрить свой код. Символ % может быть результатом URL-кодирования.
  • AND EXTRACTVALUE(...) — логический оператор AND используется для добавления условия. Функция EXTRACTVALUE() в MySQL предназначена для извлечения значения из XML-документа, но при неправильном использовании она генерирует ошибку, которая выводится в ответе сервера. Злоумышленник эксплуатирует эту особенность для получения данных.
  • 4742 — это просто число, переданное в качестве первого аргумента. Оно может быть произвольным, но часто используется для проверки, что функция выполняется.
  • CONCAT(0x7e, ((SELECT (ELT(4742=4742,1)))), 0x7e) — функция CONCAT объединяет строки. Здесь 0x7e — это шестнадцатеричное представление символа ~ (тильда), который используется как разделитель. Внутри вложенного запроса SELECT (ELT(4742=4742,1)) применяется функция ELT(). ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае 4742=4742 — это условие, которое всегда истинно (1), поэтому ELT(1,1) вернёт строку '1'. Если бы условие было ложным, ELT(0,1) вернул бы NULL. Таким образом, злоумышленник может проверять истинность различных условий, подставляя их вместо 4742=4742.
  • -- - — это комментарий, который обрезает оставшуюся часть оригинального SQL-запроса, чтобы избежать синтаксических ошибок.

В целом, запрос заставляет MySQL выполнить EXTRACTVALUE(4742, CONCAT('~', (SELECT ...), '~')). Функция EXTRACTVALUE ожидает, что второй аргумент будет корректным XPath-выражением. Если это не так, она выдаёт ошибку вида XPATH syntax error: '~...~'. В эту ошибку подставляется результат подзапроса, что позволяет злоумышленнику увидеть данные, которые он запрашивает. В нашем случае подзапрос возвращает '1', поэтому ошибка будет содержать '~1~'.

Зачем это нужно злоумышленнику?

Основная цель — получить информацию из базы данных. Подставляя вместо 4742=4742 другие условия, например, (SELECT SUBSTRING(password,1,1) FROM users LIMIT 1)='a', атакующий может посимвольно извлекать пароли, имена пользователей, версию СУБД и другие данные. Так как ошибка выводится на страницу (если приложение не подавляет ошибки), злоумышленник видит результат. Если вывод ошибок отключён, используется слепая инъекция, но в данном случае расчёт на то, что ошибки отображаются.

Функция EXTRACTVALUE — не единственная, используемая для error-based инъекций. Также применяются UPDATEXML, GTID_SUBSET и другие. Однако EXTRACTVALUE и UPDATEXML наиболее популярны из-за простоты.

Как защититься?

Чтобы предотвратить подобные атаки, необходимо следовать лучшим практикам безопасности:

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

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

Заключение

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

Источники