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

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

Подобные строки можно встретить в логах веб-серверов, в отчётах систем обнаружения вторжений (IDS) или в специализированных уязвимых приложениях (например, DVWA, SQLZoo), предназначенных для обучения пентестеров. Они не являются частью легитимного кода, а служат инструментом атаки.

Разбор структуры инъекции

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

1. )))

Три закрывающие скобки. В контексте SQL-запроса они могут закрывать ранее открытые скобки в уязвимом параметре. Например, если исходный запрос выглядит как SELECT * FROM users WHERE id = (('$input')), то вставка ))) позволит «выровнять» синтаксис и добавить собственные условия.

2. AND

Логический оператор, который присоединяет нашу инъекцию к оригинальному условию. Он гарантирует, что внедряемый код выполнится только если предыдущее выражение истинно (или в сочетании с другими операторами).

3. EXTRACTVALUE(1152, CONCAT(...))

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

Первый аргумент — 1152 — произвольное число, которое в данном случае не играет роли (может быть любым). Второй аргумент — CONCAT(0x7e, ((SELECT (ELT(1152=1152,1)))), 0x7e) — конструирует строку, которая будет вставлена в сообщение об ошибке.

4. CONCAT(0x7e, ..., 0x7e)

CONCAT объединяет несколько строк. Здесь 0x7e — это шестнадцатеричное представление символа ~ (тильда). Тильды используются как маркеры, чтобы облегчить поиск выводимых данных в тексте ошибки. Между ними помещается результат подзапроса.

5. (SELECT (ELT(1152=1152,1)))

Вложенный подзапрос, который возвращает значение. ELT — функция MySQL, возвращающая N-й элемент из списка строк. Синтаксис: ELT(N, строка1, строка2, ...). В данном случае 1152=1152 — это выражение, которое всегда истинно (1). Таким образом, ELT(1, 1) вернёт строку '1'. Фактически это простейший пример: инъекция выведет число 1, чтобы продемонстрировать работоспособность. В реальной атаке вместо 1 мог бы стоять подзапрос, извлекающий имя пользователя, хеш пароля, версию БД и т.д.

6. -- -

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

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

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

SELECT * FROM articles WHERE id = $id;

Злоумышленник передаёт в параметр id строку:

1 ))) AND EXTRACTVALUE(1152,CONCAT(0x7e,((SELECT (ELT(1152=1152,1)))),0x7e))-- -

После подстановки запрос принимает вид:

SELECT * FROM articles WHERE id = 1 ))) AND EXTRACTVALUE(1152,CONCAT(0x7e,((SELECT (ELT(1152=1152,1)))),0x7e))-- -;

MySQL пытается выполнить EXTRACTVALUE с некорректным XPath (второй аргумент не является валидным XPath-выражением), что вызывает ошибку вида:

XPATH syntax error: '~1~'

В тексте ошибки мы видим ~1~ — это и есть результат выполнения подзапроса, обрамлённый тильдами. Если приложение выводит ошибки СУБД на экран, злоумышленник получает данные. Если ошибки скрыты, атака может не сработать, но часто разработчики забывают отключить вывод ошибок в production.

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

Error-based SQL-инъекция — один из методов извлечения информации из базы данных, когда другие каналы (например, UNION-based или blind) недоступны. Основные цели:

  • Получение версии MySQL, имени текущей базы данных, пользователя.
  • Извлечение имён таблиц и столбцов через information_schema.
  • Чтение конфиденциальных данных: логинов, паролей (хешей), персональной информации.

Функция EXTRACTVALUE — не единственная, эксплуатируемая таким образом. Аналогично работают UPDATEXML, GTID_SUBSET, JSON_KEYS и другие функции, вызывающие ошибки с контролируемым текстом.

Меры защиты

Чтобы предотвратить подобные атаки, необходимо:

  • Использовать подготовленные выражения (prepared statements) с параметризацией запросов.
  • Применять ORM или библиотеки, автоматически экранирующие пользовательский ввод.
  • Отключить вывод ошибок СУБД в production-окружении (display_errors = Off).
  • Ограничить права пользователя БД, от имени которого работает приложение (принцип наименьших привилегий).
  • Регулярно обновлять MySQL: в версии 8.0.17 функция EXTRACTVALUE удалена, что снижает риск таких инъекций.
  • Использовать WAF (Web Application Firewall) для фильтрации подозрительных конструкций.

Заключение

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

Источники