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

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

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

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

Давайте разберём эту строку на составляющие, чтобы понять, как она работает.

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

Таким образом, вся конструкция заставляет MySQL выполнить подзапрос, а затем попытаться использовать его результат как часть XPath. Поскольку XPath содержит недопустимые символы (например, ~), MySQL генерирует ошибку вида: XPATH syntax error: '~1~'. Злоумышленник, видя эту ошибку, получает искомые данные.

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

Основная цель — получить информацию о базе данных: версию СУБД, имена таблиц, столбцов, логины и пароли пользователей. Error-based инъекции позволяют делать это пошагово, извлекая по одному значению за раз. В приведённом примере извлекается просто число 1, но если заменить подзапрос на, например, (SELECT version()), то в ошибке появится версия MySQL.

Такие атаки особенно опасны, потому что не требуют слепого перебора и работают быстро. Они возможны, когда приложение не фильтрует пользовательский ввод и выводит ошибки базы данных.

Как работает функция EXTRACTVALUE?

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

Важно: начиная с MySQL 8.0.17 функция EXTRACTVALUE удалена. Однако во многих старых системах она всё ещё доступна, что делает этот вектор атаки актуальным.

Пример уязвимого запроса

Предположим, в приложении есть такой SQL-запрос:

SELECT * FROM users WHERE id = '$id'

Если злоумышленник передаст в параметр id значение 1`) AND EXTRACTVALUE(7454,CONCAT(0x7e,((SELECT (ELT(7454=7454,1)))),0x7e))-- -, то итоговый запрос станет:

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

База данных выполнит подзапрос, попытается вычислить XPath и выдаст ошибку, которая отобразится пользователю (если вывод ошибок включён).

Как защититься от error-based SQL-инъекций?

Основные меры защиты:

  1. Использование подготовленных выражений (prepared statements). Это самый надёжный способ. Параметры передаются отдельно от SQL-кода, и внедрение становится невозможным.
  2. Экранирование специальных символов. Если по каким-то причинам нельзя использовать подготовленные выражения, необходимо экранировать все пользовательские данные с помощью функций типа mysqli_real_escape_string.
  3. Отключение вывода ошибок БД. Не показывайте пользователям сообщения об ошибках базы данных. Логируйте их, но не выводите на экран.
  4. Ограничение прав пользователя БД. Приложение должно работать под учётной записью с минимально необходимыми правами. Это не предотвратит инъекцию, но снизит ущерб.
  5. Использование WAF (Web Application Firewall). Современные WAF могут обнаруживать и блокировать попытки SQL-инъекций по сигнатурам.
  6. Регулярное обновление СУБД. В новых версиях MySQL опасные функции удалены или исправлены.

Заключение

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

Источники