Что такое SQL-инъекция с EXTRACTVALUE?

SQL-инъекция — один из самых распространённых способов атаки на веб-приложения, при котором злоумышленник внедряет произвольный SQL-код в запросы к базе данных. Особое место среди таких атак занимает техника, основанная на функции EXTRACTVALUE (или её аналогах вроде UPDATEXML). Она позволяет извлекать данные из базы, даже если приложение не выводит результаты запроса напрямую — информация «утекает» через сообщения об ошибках.

Рассматриваемая полезная нагрузка: %')) AND EXTRACTVALUE(7132,CONCAT(0x7e,((SELECT (ELT(7132=7132,1)))),0x7e))-- - — это типичный пример error-based SQL-инъекции. Давайте разберём её по частям.

Анатомия вредоносного запроса

Начнём с начала строки. Символы %')) — это попытка закрыть ранее открытые кавычки и скобки в уязвимом SQL-запросе. Знак % часто используется как wildcard в LIKE-запросах, но здесь он, скорее всего, часть исходного параметра. Далее идёт AND EXTRACTVALUE(7132,CONCAT(...)) — это и есть ядро атаки.

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

В нашем случае вторым аргументом идёт CONCAT(0x7e, ((SELECT (ELT(7132=7132,1)))), 0x7e). Разберём:

  • 0x7e — это шестнадцатеричное представление символа ~ (тильда). Он используется как маркер начала и конца выводимых данных, чтобы их было легко найти в тексте ошибки.
  • ELT(7132=7132, 1) — функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Выражение 7132=7132 всегда истинно (равно 1), поэтому ELT(1, 1) вернёт строку '1'. Это простейший пример; на практике вместо 1 подставляются подзапросы, извлекающие имена таблиц, колонок или хэши паролей.
  • SELECT (ELT(...)) — обёртка, позволяющая использовать подзапрос.

Завершающая часть -- - — это комментарий, который отсекает остаток оригинального SQL-запроса, чтобы синтаксис остался корректным.

Как это работает на практике

Предположим, уязвимый запрос выглядит так:

SELECT * FROM users WHERE name = '$input';

Если подставить нашу нагрузку, запрос превратится в:

SELECT * FROM users WHERE name = '%')) AND EXTRACTVALUE(7132,CONCAT(0x7e,((SELECT (ELT(7132=7132,1)))),0x7e))-- -';

База данных выполнит EXTRACTVALUE с аргументом ~1~. Поскольку ~1~ не является корректным XPath, возникнет ошибка вида: XPATH syntax error: '~1~'. В этом сообщении мы увидим результат выполнения подзапроса — в данном случае просто 1. Если заменить ELT(7132=7132,1) на, например, (SELECT password FROM users LIMIT 1), то в ошибке отобразится пароль первого пользователя.

Таким образом, атакующий может последовательно извлекать любые данные, к которым имеет доступ уязвимый запрос: версию СУБД, имена таблиц, колонок, логины и пароли. Это делает error-based инъекции чрезвычайно опасными, так как они не требуют слепого перебора и дают мгновенный результат.

Почему EXTRACTVALUE, а не другие функции?

Функция EXTRACTVALUE долгое время была популярна среди пентестеров из-за простоты и надёжности. Однако начиная с MySQL 5.7.9 она помечена как устаревшая, а в MySQL 8.0 удалена. Тем не менее, многие веб-приложения до сих пор работают на старых версиях СУБД, поэтому угроза сохраняется. Аналогичный эффект дают UPDATEXML и GTID_SUBSET.

Меры защиты от SQL-инъекций

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

  • Применять ORM (например, Hibernate, Entity Framework), которые автоматически экранируют опасные символы.
  • Ограничивать права пользователя базы данных: не давать ему доступ к системным таблицам и лишним операциям.
  • Отключить вывод подробных ошибок СУБД в production-окружении, чтобы злоумышленник не получал текст ошибки с данными.
  • Регулярно обновлять СУБД и фреймворки, чтобы использовать исправленные версии.
  • Проводить аудит кода и пентесты для выявления уязвимостей.
По данным OWASP, SQL-инъекции входят в топ-10 критических угроз веб-приложений уже более десяти лет. Внедрение параметризованных запросов позволяет устранить до 95% таких атак.

Заключение

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

Источники