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

SQL-инъекция — один из самых распространённых и опасных видов атак на веб-приложения. Согласно OWASP Top 10, она стабильно входит в список критических угроз. Один из методов эксплуатации — error-based SQL-инъекция, при которой злоумышленник заставляет базу данных выдать сообщение об ошибке, содержащее конфиденциальные данные. Функция EXTRACTVALUE() в MySQL часто используется для таких атак.

В запросе пользователя: " OR EXTRACTVALUE(7520,CONCAT(0x7e,((SELECT (ELT(7520=7520,1)))),0x7e))-- - — виден классический пример внедрения. Давайте разберём его по частям.

Как работает EXTRACTVALUE в MySQL

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

Например, запрос:

SELECT EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e));

вернёт ошибку: XPATH syntax error: '~5.7.23~'. Таким образом, версия СУБД будет выведена в сообщении об ошибке.

Разбор инъекции из запроса

Рассмотрим внедрение: " OR EXTRACTVALUE(7520,CONCAT(0x7e,((SELECT (ELT(7520=7520,1)))),0x7e))-- -.

  • " — закрывает строковый литерал в уязвимом запросе.
  • OR — логический оператор, который делает условие всегда истинным (если правая часть вернёт истину или ошибку).
  • EXTRACTVALUE(7520, ...) — вызов функции. Первый аргумент (7520) — произвольное число, не влияет на результат.
  • CONCAT(0x7e, ..., 0x7e) — объединяет символ ~ (0x7e) с полезной нагрузкой, чтобы отделить данные в сообщении об ошибке.
  • (SELECT (ELT(7520=7520,1))) — подзапрос, возвращающий 1, так как условие 7520=7520 истинно. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь возвращается 1.
  • -- - — комментарий, обрезающий остаток оригинального запроса.

В результате MySQL попытается вычислить XPath-выражение ~1~, что вызовет ошибку XPATH syntax error: '~1~'. Это простейший пример. На практике вместо 1 подставляют подзапросы, извлекающие имена таблиц, колонок, пароли пользователей.

Примеры извлечения данных

Допустим, есть таблица users с колонками username, password. Злоумышленник может выполнить:

" OR EXTRACTVALUE(1, CONCAT(0x7e, (SELECT CONCAT(username, 0x3a, password) FROM users LIMIT 1), 0x7e))-- -

В ответе придёт ошибка с логином и паролем первого пользователя. Если в таблице несколько строк, можно перебирать их через LIMIT с смещением.

Однако есть ограничение: функция EXTRACTVALUE возвращает не более 32 символов. Для обхода используют SUBSTRING или MID.

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

Помимо EXTRACTVALUE, в MySQL есть UPDATEXML(), которая работает аналогично. Также существуют методы, основанные на делении на ноль, неверных типах данных и т.п. Но EXTRACTVALUE и UPDATEXML наиболее популярны из-за простоты и наглядности.

Важно: в MySQL 5.7+ и в MariaDB эти функции всё ещё доступны, но в новых версиях (MySQL 8.0) они помечены как устаревшие и могут быть удалены в будущем. Тем не менее, на многих серверах они работают.

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

Основной способ защиты — использование параметризованных запросов (prepared statements). Это исключает возможность внедрения SQL-кода, так как данные передаются отдельно от структуры запроса.

  • Параметризация: Всегда используйте подготовленные выражения в PDO, mysqli или ORM.
  • Экранирование: Если параметризация невозможна, применяйте функции экранирования (mysqli_real_escape_string), но это менее надёжно.
  • Валидация ввода: Проверяйте типы данных, ограничивайте длину, используйте белые списки.
  • Минимизация привилегий: Учётная запись БД для веб-приложения не должна иметь прав на чтение системных таблиц или выполнение опасных функций.
  • Отключение вывода ошибок: Не показывайте пользователям сообщения об ошибках СУБД — это лишает атакующего обратной связи.
  • WAF: Веб-приложения могут быть защищены с помощью Web Application Firewall, который блокирует подозрительные запросы.

Также рекомендуется регулярно обновлять СУБД и фреймворки, проводить аудит кода и пентесты.

Заключение

SQL-инъекция через EXTRACTVALUE — это мощный инструмент в руках злоумышленника, позволяющий извлекать данные из базы через сообщения об ошибках. Понимание механизма работы помогает разработчикам осознать важность защиты. Используйте параметризованные запросы, ограничивайте права БД и не выводите ошибки пользователю — это сведёт риск к минимуму.

Источники