Встречая в логах или на форумах строку вида %" AND EXTRACTVALUE(8515,CONCAT(0x7e,((SELECT (ELT(8515=8515,1)))),0x7e))-- -, многие задаются вопросом: что это и какую угрозу несёт? Это не случайный набор символов, а классический пример error-based SQL-инъекции для СУБД MySQL. Злоумышленник использует уязвимость в обработке пользовательского ввода, чтобы через сообщение об ошибке извлечь данные из базы. В этой статье мы детально разберём, как работает такая инъекция, какие функции задействованы и как защититься.

Что такое error-based SQL-инъекция?

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

В MySQL для этого часто используют функции EXTRACTVALUE и UPDATEXML. Они предназначены для работы с XML, но при некорректных аргументах возвращают ошибку, в которой может отобразиться переданная строка.

Разбор конкретной строки

Рассмотрим запрос по частям:

%" AND EXTRACTVALUE(8515,CONCAT(0x7e,((SELECT (ELT(8515=8515,1)))),0x7e))-- -

  • %" — это часть исходного запроса, куда внедряется инъекция. Символ % часто используется в LIKE-запросах, а кавычка закрывает строковый литерал, делая дальнейший код частью SQL-выражения.
  • AND — логический оператор, присоединяющий вредоносное условие.
  • EXTRACTVALUE(8515, ...) — вызов функции. Первый аргумент (8515) — произвольное число, не влияет на результат, но должен быть допустимым XML-фрагментом? На самом деле EXTRACTVALUE ожидает первым аргументом XML-строку. Если передать число, MySQL может выдать ошибку, но в контексте инъекции это не важно — главное, чтобы функция выполнилась и вернула ошибку с внедрёнными данными.
  • CONCAT(0x7e, ..., 0x7e) — конкатенация символов тильды (0x7e) с подзапросом. Тильды служат маркерами, по которым легко найти полезную нагрузку в сообщении об ошибке.
  • (SELECT (ELT(8515=8515,1))) — подзапрос, возвращающий результат выражения ELT(8515=8515,1). Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 8515=8515 — всегда истина (1), поэтому ELT(1,1) вернёт '1'. Это простейший пример; на практике вместо этого подзапроса злоумышленник подставляет запросы к системным таблицам, например SELECT version() или SELECT table_name FROM information_schema.tables.
  • -- - — комментарий, обрезающий остаток исходного SQL-запроса, чтобы не возникло синтаксической ошибки.

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

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

Функция EXTRACTVALUE(XML_frag, XPath_expr) принимает два строковых аргумента: фрагмент XML-разметки и выражение XPath. Она возвращает текст (CDATA) первого текстового узла, который является дочерним для элемента, соответствующего XPath-выражению. Если XPath-выражение некорректно, MySQL выдаёт ошибку с указанием проблемного фрагмента. Именно это свойство и эксплуатируется при error-based инъекции.

Важно понимать, что EXTRACTVALUE устарела начиная с MySQL 5.7.6 и удалена в MySQL 8.0. В современных версиях для аналогичных атак используют другие функции, например UPDATEXML или GTID_SUBSET, но принцип остаётся тем же.

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

Основная цель — получить информацию о базе данных, которую затем можно использовать для дальнейших атак. С помощью error-based инъекции можно извлечь:

  • версию СУБД;
  • имя текущей базы данных;
  • список таблиц и колонок;
  • учётные данные пользователей (логины, хеши паролей);
  • любые другие данные, хранящиеся в БД.

Поскольку данные выводятся в сообщении об ошибке, атакующему не нужны специальные условия, такие как вывод результатов на странице (union-based) или временные задержки (time-based). Это делает error-based инъекцию удобной и быстрой.

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

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

SELECT * FROM products WHERE name LIKE '%" + user_input + "%'

Если пользователь введёт %" AND EXTRACTVALUE(8515,CONCAT(0x7e,(SELECT version()),0x7e))-- -, то итоговый запрос примет вид:

SELECT * FROM products WHERE name LIKE '%" AND EXTRACTVALUE(8515,CONCAT(0x7e,(SELECT version()),0x7e))-- -%'

MySQL выполнит подзапрос SELECT version(), получит, например, 5.7.33, затем попытается использовать это значение как XPath. Возникнет ошибка: XPATH syntax error: '~5.7.33~'. Атакующий увидит версию СУБД.

Как защититься от error-based SQL-инъекций

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

  • Экранирование специальных символов — но это менее надёжно, чем параметризация.
  • Валидация и фильтрация входных данных — например, отклонение запросов, содержащих подозрительные конструкции.
  • Ограничение прав пользователя БД — приложение должно работать с минимально необходимыми привилегиями, чтобы даже при успешной инъекции ущерб был меньше.
  • Отключение вывода ошибок на продакшене — сообщения об ошибках не должны попадать в браузер пользователя. Логирование ошибок на сервере помогает разработчикам, но не раскрывает информацию атакующим.
  • Использование WAF — веб-application firewall может блокировать известные шаблоны атак, но не является панацеей.

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

Заключение

Строка с EXTRACTVALUE — это не просто случайный набор символов, а рабочий инструмент злоумышленника для извлечения данных из базы MySQL через сообщения об ошибках. Понимание механизма таких атак помогает разработчикам и администраторам своевременно закрывать уязвимости. Помните: безопасность веб-приложения начинается с безопасной работы с базой данных.

Источники