Что это за строка?

Строка )))) AND EXTRACTVALUE(9405,CONCAT(0x7e,((SELECT (ELT(9405=9405,1)))),0x7e))-- - представляет собой классический пример error-based SQL-инъекции для СУБД MySQL. Она предназначена для извлечения данных из базы через вывод сообщения об ошибке, которое генерируется функцией EXTRACTVALUE при передаче ей специально сформированного аргумента.

Подобные строки часто встречаются в отчётах об уязвимостях, в логах веб-серверов или в материалах по пентесту. Они не являются вредоносным кодом сами по себе, но демонстрируют методику эксплуатации недостаточной фильтрации входных данных в SQL-запросах.

Разбор компонентов инъекции

Рассмотрим каждый элемент строки подробно.

1. Начальные символы `))))`

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

2. Оператор `AND`

Логический оператор AND присоединяет внедряемое условие к исходному запросу. Если исходный запрос был истинным, то добавление AND ... позволит выполнить внедряемую функцию только при выполнении определённых условий. В данном случае это необходимо для того, чтобы функция EXTRACTVALUE вызвалась и сгенерировала ошибку.

3. Функция `EXTRACTVALUE(9405, CONCAT(...))`

EXTRACTVALUE — это встроенная функция MySQL (до версии 8.0.17 включительно), предназначенная для извлечения значения из XML-строки по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_frag, XPath_expr).

Если второй аргумент не является корректным XPath-выражением, MySQL возвращает ошибку XPATH syntax error, в тексте которой отображается переданная строка. Это и используется для извлечения данных: злоумышленник подставляет в XPath результат подзапроса, и СУБД возвращает его в сообщении об ошибке.

Первый аргумент 9405 — произвольное число, которое в данном случае не играет роли, так как всё равно будет вызвана ошибка из-за второго аргумента.

4. `CONCAT(0x7e, (SELECT (ELT(9405=9405,1))), 0x7e)`

Функция CONCAT объединяет несколько строк. Здесь используется:

  • 0x7e — шестнадцатеричное представление символа ~ (тильда). Тильда добавляется в начало и конец, чтобы отделить выводимые данные от остального текста ошибки и облегчить их извлечение.
  • (SELECT (ELT(9405=9405,1))) — подзапрос, возвращающий результат функции ELT.

ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае ELT(9405=9405, 1) — условие 9405=9405 всегда истинно, что в числовом контексте даёт 1. Значит, ELT(1, 1) вернёт строку '1'. Это простейший пример, демонстрирующий работу конструкции. В реальной атаке вместо 1 могло бы быть имя пользователя, хеш пароля или другая конфиденциальная информация, полученная через подзапрос.

5. Завершающая последовательность `-- -`

Два дефиса и пробел (или дефис) — это комментарий в SQL. Всё, что идёт после -- , игнорируется парсером. Это позволяет «отрезать» остаток оригинального запроса, который мог бы помешать выполнению инъекции. Пробел после дефисов обязателен в некоторых реализациях MySQL, поэтому часто пишут -- - или --+.

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

Предположим, на сервере выполняется запрос вида:

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

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

SELECT * FROM users WHERE id = ')))) AND EXTRACTVALUE(9405,CONCAT(0x7e,((SELECT (ELT(9405=9405,1)))),0x7e))-- -';

После подстановки MySQL попытается выполнить EXTRACTVALUE с некорректным XPath, что вызовет ошибку:

XPATH syntax error: '~1~'

В тексте ошибки мы видим ~1~ — это результат выполнения подзапроса. Если бы вместо 1 стоял, например, (SELECT password FROM users LIMIT 1), в ошибке отобразился бы пароль.

Почему это опасно?

Error-based SQL-инъекции через EXTRACTVALUE (а также через UPDATEXML) позволяют злоумышленнику извлекать произвольные данные из базы, если приложение не фильтрует входные параметры и выводит ошибки СУБД пользователю. Это может привести к утечке конфиденциальной информации, компрометации учётных записей и полному захвату базы данных.

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

Как защититься?

  • Используйте параметризованные запросы (prepared statements). Это самый надёжный способ предотвратить SQL-инъекции, так как данные не попадают в текст запроса напрямую.
  • Экранируйте специальные символы. Если параметризация невозможна, применяйте функции экранирования, предоставляемые драйвером БД.
  • Отключите вывод ошибок СУБД в продакшене. Сообщения об ошибках не должны показываться пользователю — это затрудняет эксплуатацию error-based инъекций.
  • Обновляйте СУБД. В новых версиях MySQL опасные функции могут быть удалены или изменены.
  • Проводите регулярные сканирования уязвимостей. Используйте автоматические сканеры и ручной аудит кода.

Заключение

Строка )))) AND EXTRACTVALUE(9405,CONCAT(0x7e,((SELECT (ELT(9405=9405,1)))),0x7e))-- - — это учебный пример эксплуатации error-based SQL-инъекции в MySQL. Она показывает, как через функцию EXTRACTVALUE можно заставить СУБД вывести произвольные данные в сообщении об ошибке. Понимание таких векторов атак необходимо для разработки безопасных веб-приложений и защиты баз данных.

Источники