Введение
SQL-инъекции остаются одной из самых распространённых уязвимостей веб-приложений. Среди них особое место занимают error-based инъекции, когда злоумышленник извлекает данные через сообщения об ошибках базы данных. Функция EXTRACTVALUE в MySQL часто используется для таких атак. В этой статье мы детально разберём запрос "))) AND EXTRACTVALUE(3499,CONCAT(0x7e,((SELECT (ELT(3499=3499,1)))),0x7e))-- - и объясним, как он работает и как от него защититься.
Что такое EXTRACTVALUE?
EXTRACTVALUE — это встроенная функция MySQL, предназначенная для извлечения значения из XML-документа с помощью выражения XPath. Синтаксис: EXTRACTVALUE(XML_frag, XPath_expr). Она возвращает текст первого узла, соответствующего XPath-выражению. Если XML-фрагмент некорректен или XPath-выражение не соответствует ни одному узлу, функция генерирует ошибку. Именно это свойство и используется в error-based SQL-инъекциях.
Разбор инъекционного запроса
Рассмотрим строку: "))) AND EXTRACTVALUE(3499,CONCAT(0x7e,((SELECT (ELT(3499=3499,1)))),0x7e))-- -
Она состоит из нескольких частей:
")))— закрывающие кавычки и скобки, которые завершают оригинальный SQL-запрос, чтобы внедрить свой код.AND EXTRACTVALUE(...)— логическое условие, которое всегда истинно, если функция не вызовет ошибку.EXTRACTVALUE(3499, CONCAT(0x7e, ((SELECT (ELT(3499=3499,1)))), 0x7e))— вызов функции с двумя аргументами.-- -— комментарий, обрезающий остаток оригинального запроса.
Аргументы EXTRACTVALUE
Первый аргумент — 3499 — это произвольное число, которое не является корректным XML-документом. Второй аргумент — результат CONCAT. Он объединяет тильду (0x7e — шестнадцатеричный код символа ~), затем результат подзапроса SELECT (ELT(3499=3499,1)), и снова тильду. Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 3499=3499 — истина (1), поэтому ELT возвращает первую строку — 1. Таким образом, CONCAT выдаёт строку ~1~.
Однако EXTRACTVALUE ожидает первым аргументом XML-фрагмент. Число 3499 не является XML, поэтому MySQL пытается его разобрать и выдаёт ошибку: XPATH syntax error: '~1~'. В сообщении об ошибке отображается переданная строка, что позволяет злоумышленнику увидеть результат выполнения подзапроса. В данном случае это просто число 1, но вместо него может быть любое выражение, например, имя пользователя или хеш пароля.
Зачем это нужно?
Цель такой инъекции — заставить базу данных вернуть данные в тексте ошибки. Поскольку приложение часто выводит ошибки СУБД на экран (или они попадают в логи), атакующий может извлекать произвольную информацию: версию MySQL, имена таблиц, логины и пароли. Это классический пример error-based SQL-инъекции.
Пример практического использования
Предположим, есть уязвимый параметр id в URL: http://example.com/product.php?id=1. Злоумышленник может подставить:
1 AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))
В ответе появится ошибка вида: XPATH syntax error: '~5.7.23~', что раскроет версию СУБД. Аналогично можно получить имя базы данных, таблицы и т.д.
Ограничения и особенности
Функция EXTRACTVALUE работает только в MySQL и MariaDB. В других СУБД (PostgreSQL, MSSQL, Oracle) используются иные приёмы. Кроме того, в MySQL 5.7+ длина выводимой строки ограничена 32 символами, поэтому для извлечения длинных данных применяют посимвольное чтение с помощью SUBSTRING и смещений.
Также важно, чтобы приложение выводило ошибки БД. Если ошибки подавляются, error-based инъекция не сработает, и атакующий переключится на blind-инъекции.
Как защититься?
Основные меры предотвращения SQL-инъекций:
- Использование подготовленных выражений (prepared statements) с параметризацией запросов. Это самый надёжный способ, так как данные не попадают в SQL-код напрямую.
- Экранирование специальных символов с помощью функций вроде
mysqli_real_escape_string(но это менее надёжно, чем подготовленные выражения). - Отключение вывода ошибок БД на продакшене. Ошибки должны логироваться, но не показываться пользователю.
- Ограничение прав пользователя БД: приложению не нужны права на чтение системных таблиц или выполнение опасных функций.
- Использование WAF (Web Application Firewall) для фильтрации подозрительных запросов.
- Регулярное обновление СУБД и фреймворков.
Важно понимать, что фильтрация по чёрным спискам (например, удаление слова EXTRACTVALUE) неэффективна, так как злоумышленник может использовать обфускацию или другие функции.
Заключение
SQL-инъекция через EXTRACTVALUE — это мощный инструмент в руках злоумышленника, позволяющий извлекать данные через сообщения об ошибках. Понимание механизма работы помогает разработчикам и специалистам по безопасности правильно выстраивать защиту. Главный совет: всегда используйте параметризованные запросы и не выводите ошибки БД конечным пользователям.
Если вы нашли подобную уязвимость на своём сайте, немедленно устраните её, чтобы предотвратить утечку данных.
Комментарии
—Войдите, чтобы оставить комментарий