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

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

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

Разбор по частям

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

1. ))) — закрытие скобок

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

2. AND EXTRACTVALUE(8892, ...)

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

Первый аргумент 8892 — произвольное число, оно не играет роли, кроме заполнения места.

3. CONCAT(0x7e, ((SELECT (ELT(8892=8892,1)))), 0x7e)

  • 0x7e — шестнадцатеричный код символа ~ (тильда). Тильда используется как маркер, чтобы в сообщении об ошибке было легко найти границы выведенных данных.
  • ELT(N, str1, str2, ...) — функция, возвращающая N-ю строку из списка. Если N=1, вернётся str1.
  • 8892=8892 — всегда истинное условие, результат 1. То есть ELT(1, 1) вернёт строку '1'.
  • Конструкция ((SELECT (ELT(...)))) — подзапрос, возвращающий значение. В реальной атаке вместо ELT(8892=8892,1) подставляют вызовы вроде SELECT version(), SELECT user(), SELECT table_name FROM information_schema.tables и т.п.

Таким образом, CONCAT склеивает тильду, результат подзапроса и ещё одну тильду. Затем EXTRACTVALUE пытается разобрать эту строку как XPath и выдаёт ошибку, в тексте которой появляется склеенное значение.

4. -- - — комментарий

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

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

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

SELECT * FROM articles WHERE id = ('$id')

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

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

СУБД выполнит EXTRACTVALUE, получит ошибку вида:

XPATH syntax error: '~1~'

В сообщении об ошибке злоумышленник увидит значение 1. Если заменить ELT(8892=8892,1) на SELECT version(), в ошибке появится версия MySQL. Так пошагово можно извлечь имена таблиц, колонок, логины и пароли пользователей.

Зачем это нужно атакующему?

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

  • Получение версии СУБД и имени пользователя.
  • Чтение структуры базы: таблицы, колонки.
  • Извлечение конфиденциальных данных: логины, хеши паролей, персональные данные.
  • Иногда — выполнение произвольных команд через LOAD_FILE или запись файлов.

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

Главная рекомендация — использовать параметризованные запросы (prepared statements). Тогда пользовательский ввод никогда не станет частью SQL-кода. Дополнительные меры:

  • Отключить вывод ошибок базы данных в продакшене (display_errors = Off).
  • Использовать ORM и экранирование, но не полагаться только на них.
  • Регулярно проводить аудит кода и сканирование уязвимостей.
  • Ограничить права пользователя базы данных, от имени которого работает приложение.

Заключение

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

Источники