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

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

Запрос, который вы видите в заголовке — %"))) AND EXTRACTVALUE(4631,CONCAT(0x7e,((SELECT (ELT(4631=4631,1)))),0x7e))-- - — это классический пример эксплуатации уязвимости. Давайте разберём его по частям.

Как работает функция ExtractValue в MySQL

Функция EXTRACTVALUE() предназначена для извлечения значения из XML-документа по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_document, XPath_expression). Если XPath-выражение некорректно, MySQL возвращает ошибку с сообщением: XPATH syntax error: '...'. Именно эта особенность и используется хакерами: они могут поместить в XPath-выражение результат подзапроса, и он отобразится в тексте ошибки.

Например, запрос SELECT EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e)); вызовет ошибку вида XPATH syntax error: '~5.7.23~', раскрывая версию СУБД. Символ 0x7e — это тильда (~), используемая как маркер начала и конца выводимых данных.

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

Рассмотрим запрос %"))) AND EXTRACTVALUE(4631,CONCAT(0x7e,((SELECT (ELT(4631=4631,1)))),0x7e))-- -:

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

В результате выполнения такого запроса MySQL сгенерирует ошибку, в тексте которой будет выведено значение ~1~. В реальной атаке вместо ELT(4631=4631,1) подставляются подзапросы к системным таблицам (например, INFORMATION_SCHEMA) для извлечения имён таблиц, колонок и самих данных.

Пошаговый пример эксплуатации

Предположим, уязвимый параметр передаётся в URL: https://example.com/product?id=1. Злоумышленник может отправить:

id=1 AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT table_name FROM information_schema.tables LIMIT 0,1), 0x7e))

В ответе сервера появится ошибка с именем первой таблицы. Меняя LIMIT, можно перебрать все таблицы, затем колонки и, наконец, извлечь логины и пароли пользователей.

Важно: подобные действия являются незаконными и преследуются по закону. Данная информация предоставлена исключительно в образовательных целях для защиты своих систем.

Другие функции для error-based инъекций

Помимо EXTRACTVALUE, в MySQL существуют и другие функции, вызывающие ошибки с полезной нагрузкой:

  • UPDATEXML() — аналогична ExtractValue, но работает с XML-документом.
  • GTID_SUBSET() — в некоторых версиях MySQL вызывает ошибку с указанным значением.
  • EXP() — при переполнении возвращает ошибку с числом.
  • RAND() в сочетании с GROUP BY — классический способ вывода данных через дублирование ключей.

Выбор функции зависит от версии СУБД и настроек. Например, EXTRACTVALUE удалена в MySQL 8.0. Поэтому современные пентестеры чаще используют UPDATEXML или другие методы.

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

Основной метод защиты — использование параметризованных запросов (prepared statements). Никогда не конкатенируйте пользовательский ввод в SQL-запрос. В PHP это делается через PDO или mysqli, в Python — через параметры в курсоре, в Java — через PreparedStatement.

Дополнительные меры:

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

Заключение

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

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

Источники