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

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

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

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

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

Начало: ')))

Символы '))) — это попытка закрыть ранее открытые кавычки и скобки в исходном SQL-запросе. Злоумышленник предполагает, что уязвимый параметр вставляется внутрь выражения, например: SELECT * FROM users WHERE id = ('$input'). Чтобы синтаксис стал корректным, нужно закрыть строку и скобки. Количество скобок подбирается экспериментально.

Оператор AND

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

Функция EXTRACTVALUE()

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

Ключевая особенность: если XPath-выражение синтаксически некорректно, MySQL генерирует ошибку, в тексте которой содержится переданное выражение. Это и используется для извлечения данных.

Аргументы 7849 и CONCAT(0x7e, ..., 0x7e)

Первый аргумент — произвольное число или строка, которая не является корректным XML. Второй аргумент — результат функции CONCAT, склеивающей символ ~ (код 0x7e), некоторое выражение и снова ~. Символ ~ используется как маркер, чтобы в сообщении об ошибке легко было найти внедрённые данные.

Подзапрос (SELECT (ELT(7849=7849,1)))

Внутри CONCAT находится подзапрос, возвращающий результат функции ELT(N, str1, str2, ...). ELT возвращает N-ю строку из списка. В данном случае условие 7849=7849 всегда истинно, поэтому возвращается 1 (первая строка). Это простейшая проверка работоспособности инъекции: если ошибка появится, значит, внедрение сработало.

Комментарий -- -

Два дефиса и пробел (или дефис) — это комментарий в SQL, который отсекает оставшуюся часть исходного запроса, чтобы не нарушать синтаксис.

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

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

SELECT * FROM articles WHERE id = '$id';

Если передать в параметр id строку '))) AND EXTRACTVALUE(7849,CONCAT(0x7e,((SELECT (ELT(7849=7849,1)))),0x7e))-- -, то после подстановки получится:

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

СУБД попытается выполнить EXTRACTVALUE с первым аргументом 7849 (не XML) и вторым аргументом, содержащим символ ~. Поскольку 7849 не является корректным XML-документом, MySQL выдаст ошибку вида:

XPATH syntax error: '~1~'

В сообщении об ошибке появится ~1~ — результат выполнения подзапроса. В реальной атаке вместо ELT(7849=7849,1) подставляются вызовы, извлекающие имена таблиц, колонок, версию СУБД, логины и пароли пользователей. Например, (SELECT version()) или (SELECT table_name FROM information_schema.tables LIMIT 0,1).

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

Error-based SQL-инъекции позволяют получать данные напрямую из сообщений об ошибках, когда приложение выводит их пользователю. Это один из самых быстрых способов эксплуатации, так как не требует слепого перебора (boolean-based) или временных задержек (time-based).

Основные цели:

  • Получение версии MySQL и операционной системы.
  • Извлечение имён баз данных, таблиц и колонок через information_schema.
  • Чтение учётных данных пользователей.
  • В некоторых случаях — выполнение произвольных запросов и даже команд ОС (при наличии прав).

Меры защиты

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

  1. Использовать подготовленные выражения (prepared statements) с параметризацией — это самый надёжный способ.
  2. Экранировать специальные символы при невозможности использовать параметризацию.
  3. Отключить вывод ошибок СУБД в production-окружении, чтобы сообщения не попадали к пользователю.
  4. Ограничить права пользователя БД, от имени которого работает приложение: запретить доступ к information_schema, mysql и другим системным таблицам.
  5. Регулярно обновлять MySQL: в версии 8.0.17 функция EXTRACTVALUE была удалена, что усложняет эксплуатацию, но не отменяет необходимость других мер.
  6. Использовать WAF (Web Application Firewall) для фильтрации подозрительных запросов.

Заключение

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

Источники