Что такое SQL-инъекция через EXTRACTVALUE?

SQL-инъекция — один из самых распространённых видов атак на веб-приложения. Злоумышленник внедряет вредоносный SQL-код в запрос, чтобы получить доступ к данным, изменить их или выполнить произвольные команды. Существует несколько типов инъекций: union-based, boolean-based, time-based и error-based. Последний тип часто использует функцию EXTRACTVALUE в СУБД MySQL.

Запрос %" OR EXTRACTVALUE(4133,CONCAT(0x7e,((SELECT (ELT(4133=4133,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции. Давайте разберём его по частям.

Разбор внедряемого кода

Символы и операторы

  • %" — это часть оригинального запроса, которая, вероятно, подставляется в SQL-шаблон. Символ % часто используется как подстановочный знак в LIKE, а " закрывает строковый литерал. Злоумышленник добавляет OR, чтобы внедрить своё условие.
  • OR — логический оператор, который делает условие истинным, если хотя бы одна часть верна. Это позволяет обойти проверки.
  • EXTRACTVALUE(4133, CONCAT(0x7e, ((SELECT (ELT(4133=4133,1)))), 0x7e)) — вызов функции EXTRACTVALUE, которая извлекает значение из XML-строки по XPath-выражению. Синтаксис: EXTRACTVALUE(XML_document, XPath_expression).

Функция EXTRACTVALUE возвращает текст из XML, соответствующий XPath. Если XPath содержит ошибку, MySQL генерирует сообщение об ошибке, которое включает результат вычисления выражения. Это и есть основа error-based инъекции: злоумышленник заставляет базу данных выдать нужные данные в тексте ошибки.

Как работает EXTRACTVALUE в инъекции

В нашем случае первый аргумент — число 4133 (может быть любым). Второй аргумент — CONCAT(0x7e, ((SELECT (ELT(4133=4133,1)))), 0x7e). Функция CONCAT объединяет строки: 0x7e — это шестнадцатеричное представление символа ~ (тильда), который используется как маркер для облегчения поиска результата в сообщении об ошибке.

Внутри CONCAT выполняется подзапрос SELECT (ELT(4133=4133,1)). Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 4133=4133 — всегда истинное условие, которое возвращает 1. Таким образом, ELT(1, 1) вернёт строку '1'.

Итоговый XPath, передаваемый в EXTRACTVALUE, будет содержать тильды и результат подзапроса. Поскольку XPath синтаксически некорректен (начинается с ~), MySQL выдаст ошибку вида: XPATH syntax error: '~1~'. В этом сообщении злоумышленник увидит результат выполнения подзапроса — в данном случае '1'.

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

Error-based инъекции позволяют извлекать данные посимвольно или целыми строками, если они помещаются в сообщение об ошибке. В реальных атаках вместо ELT(4133=4133,1) подставляются подзапросы, возвращающие имена таблиц, столбцов, логины, пароли и другую конфиденциальную информацию. Например, можно получить версию СУБД, имя текущей базы данных или хеши паролей.

Ограничение: длина сообщения об ошибке обычно ограничена (около 64 символов для XPath ошибок в MySQL), поэтому данные извлекаются по частям с помощью функций SUBSTRING, MID или LIMIT.

Пример реальной атаки

Предположим, есть уязвимый параметр id в URL: http://example.com/product.php?id=1. Запрос в коде: SELECT * FROM products WHERE id = '$id'. Злоумышленник подставляет:

1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e))-- -

В ответе сервера появится ошибка с именем базы данных. Так пошагово можно вытащить всю структуру БД.

Меры защиты

Чтобы предотвратить SQL-инъекции, включая error-based через EXTRACTVALUE, необходимо:

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

Заключение

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

Источники