Введение

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

Что такое EXTRACTVALUE?

Функция EXTRACTVALUE в MySQL предназначена для извлечения значения из XML-документа по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_frag, XPath_expr). Однако при некорректном XPath-выражении функция возвращает ошибку, которая может содержать переданные данные. Это свойство активно используется в SQL-инъекциях для вывода информации.

Анализ запроса

Рассмотрим запрос по частям:

  • %'))) — попытка закрыть предыдущие скобки и кавычки, чтобы внедрить свой код.
  • AND EXTRACTVALUE(7717,CONCAT(0x7e,((SELECT (ELT(7717=7717,1)))),0x7e)) — вызов функции с параметрами. Первый аргумент — число 7717 (произвольный XML), второй — конкатенация тильды (0x7e), результата подзапроса и ещё одной тильды.
  • -- - — комментарий, отсекающий остаток оригинального запроса.

Подзапрос SELECT (ELT(7717=7717,1)) возвращает 1, так как условие истинно. ELT — функция, возвращающая N-й элемент из списка. Здесь список состоит из одного элемента 1. Таким образом, EXTRACTVALUE получает XPath-выражение вида ~1~, что не является корректным XPath, и MySQL генерирует ошибку: XPATH syntax error: '~1~'. В сообщении об ошибке отображается переданная строка, что позволяет злоумышленнику извлекать данные.

Примеры использования в атаках

Хакеры часто применяют EXTRACTVALUE для получения имён таблиц, колонок или конкретных данных. Например, заменив подзапрос на SELECT table_name FROM information_schema.tables LIMIT 1, можно получить имя первой таблицы. Ошибка покажет это имя. Аналогично можно извлечь пароли, логины и другую конфиденциальную информацию.

Ошибка 1222: разные количества колонок

В результатах поиска упоминается ошибка ERROR 1222 (21000): The used SELECT statements have a different number of columns. Она возникает при использовании UNION ALL, когда количество столбцов в объединяемых запросах не совпадает. Это классическая проблема при SQL-инъекциях через UNION. Злоумышленник должен подобрать число колонок, чтобы успешно внедрить свой SELECT. В приведённом примере с ' UNION ALL SELECT NULL,concat(0x28,username,0x3a,password,0x29) FROM users # ошибка возникла, потому что в таблице users три колонки, а в запросе указано только две (NULL и concat). Чтобы исправить, нужно добавить ещё один NULL.

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

Основные меры защиты:

  1. Параметризованные запросы (prepared statements) — самый надёжный способ. Они разделяют код и данные, делая невозможным внедрение SQL.
  2. Экранирование специальных символов — используйте функции экранирования, предоставляемые драйвером БД.
  3. Валидация входных данных — проверяйте типы, длину, допустимые символы.
  4. Ограничение прав пользователя БД — не давайте приложению лишних привилегий.
  5. Использование ORM — современные ORM-библиотеки автоматически защищают от инъекций.
  6. Регулярное обновление СУБД — в новых версиях MySQL функция EXTRACTVALUE помечена как устаревшая, но в старых она опасна.

Заключение

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

Источники