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

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

Как работает эта инъекция?

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

  • )) — закрывающие скобки, которые завершают ранее открытые конструкции в уязвимом запросе, чтобы внедрить свой код.
  • AND — логический оператор, присоединяющий наше условие к оригинальному запросу.
  • EXTRACTVALUE(7837, CONCAT(0x7e, ((SELECT (ELT(7837=7837,1)))), 0x7e)) — вызов функции EXTRACTVALUE, которая извлекает значение из XML-документа по XPath-выражению. В MySQL эта функция при некорректном XPath-выражении генерирует ошибку, текст которой содержит переданное выражение. Здесь в качестве первого аргумента передаётся число 7837 (произвольный идентификатор), а второй аргумент — результат конкатенации символа ~ (0x7e), результата подзапроса и ещё одного ~.
  • SELECT (ELT(7837=7837,1)) — подзапрос, возвращающий 1, если условие истинно. ELT возвращает N-й элемент из списка; здесь список состоит из одного элемента — 1. Это простейшая проверка, которая может быть заменена на любой другой запрос, например, на извлечение имени пользователя или хеша пароля.
  • -- - — комментарий, который отсекает оставшуюся часть оригинального SQL-запроса, чтобы не возникло синтаксической ошибки.

Когда MySQL выполняет EXTRACTVALUE с XPath-выражением, начинающимся с ~, функция пытается интерпретировать это как XPath и терпит неудачу. В сообщении об ошибке MySQL выводит что-то вроде: XPATH syntax error: '~1~'. Таким образом, результат подзапроса (в данном случае «1») отображается в тексте ошибки, которую злоумышленник может прочитать, если приложение выводит ошибки базы данных на экран.

Зачем это используется?

Error-based SQL-инъекции — один из самых простых и эффективных способов извлечения данных, когда приложение возвращает сообщения об ошибках СУБД. В отличие от blind-инъекций, где приходится задавать множество вопросов и анализировать поведение сервера, здесь нужная информация сразу попадает в ответ. Описанная строка — это шаблон, в который вместо ELT(7837=7837,1) можно подставить, например, SELECT version() или SELECT password FROM users LIMIT 1, и получить эти данные в тексте ошибки.

Опасность и защита

Подобные инъекции представляют серьёзную угрозу для веб-приложений, работающих с MySQL. Если злоумышленник может внедрить такой код, он способен получить доступ к конфиденциальной информации: учётным данным, персональным данным пользователей, коммерческой тайне. В худшем случае через SQL-инъекцию можно выполнить произвольные команды на сервере или полностью скомпрометировать базу.

Для защиты необходимо:

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

Технические детали

Функция EXTRACTVALUE() в MySQL принимает два строковых аргумента: фрагмент XML-разметки и XPath-выражение. Она возвращает текст первого текстового узла, соответствующего XPath. Однако если XPath-выражение синтаксически некорректно, MySQL генерирует ошибку с указанием проблемного фрагмента. Именно это свойство и эксплуатируется в error-based инъекциях. Стоит отметить, что в MySQL 5.7+ функция EXTRACTVALUE была удалена, поэтому данная техника работает только на старых версиях (5.1–5.6). Тем не менее, многие устаревшие системы до сих пор уязвимы.

Символ 0x7e — это тильда (~), которая используется как маркер, чтобы облегчить поиск выведенных данных в сообщении об ошибке. Часто вместо тильды применяют другие разделители, например, 0x3a (двоеточие).

Пример реального использования

Предположим, есть уязвимый URL: http://example.com/product.php?id=1. Злоумышленник может подставить вместо 1 строку 1)) AND EXTRACTVALUE(7837,CONCAT(0x7e,((SELECT (ELT(7837=7837,1)))),0x7e))-- -. Если приложение не фильтрует ввод и выводит ошибки MySQL, в ответе появится сообщение с ~1~. Заменив ELT(7837=7837,1) на SELECT database(), он получит имя текущей базы данных, затем аналогично можно извлечь имена таблиц, столбцов и сами данные.

Вывод

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

Источники