Введение

Встречая в логах веб-сервера или в поле ввода подобную строку: ) AND EXTRACTVALUE(8894,CONCAT(0x7e,((SELECT (ELT(8894=8894,1)))),0x7e))-- -, многие задаются вопросом: что это и какова её цель? Это классический пример SQL-инъекции, нацеленной на извлечение данных из базы данных через генерацию ошибок. В данной статье мы подробно разберём каждую часть этой конструкции, объясним, как она работает, и расскажем, как защитить свой сайт от подобных атак.

Что такое SQL-инъекция?

SQL-инъекция (SQL injection) — это один из самых распространённых способов взлома веб-приложений. Злоумышленник внедряет вредоносный SQL-код в запрос, который приложение отправляет базе данных. Если приложение не проверяет входные данные должным образом, этот код выполняется, что может привести к утечке конфиденциальной информации, изменению или удалению данных, а в некоторых случаях — к полному контролю над сервером.

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

Разбор конструкции AND EXTRACTVALUE(8894,CONCAT(0x7e,((SELECT (ELT(8894=8894,1)))),0x7e))-- -

Давайте разберём эту строку по частям.

1. AND

Логический оператор AND используется для добавления условия к существующему запросу. Злоумышленник пытается сделать так, чтобы внедрённое выражение выполнилось, только если исходное условие истинно (или ложно, в зависимости от логики).

2. EXTRACTVALUE(8894, CONCAT(...))

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

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

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

4. (SELECT (ELT(8894=8894,1)))

ELT — функция MySQL, возвращающая N-й элемент из списка строк. ELT(N, str1, str2, ...) возвращает strN. В данном случае ELT(8894=8894,1) — первый аргумент это логическое выражение 8894=8894, которое всегда истинно (1). Значит, ELT(1,1) вернёт строку '1'. Это простейшая проверка работоспособности инъекции. В реальных атаках вместо 1 может быть подзапрос, извлекающий имена таблиц, пароли и т.д.

5. -- -

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

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

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

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

Злоумышленник передаёт в $id значение 1' AND EXTRACTVALUE(8894,CONCAT(0x7e,((SELECT (ELT(8894=8894,1)))),0x7e))-- -. После подстановки запрос становится:

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

База данных выполняет EXTRACTVALUE. Поскольку второй аргумент содержит символ ~, который не является допустимым XPath, MySQL выдаёт ошибку вида:

XPATH syntax error: '~1~'

В тексте ошибки появляется ~1~. Это подтверждает, что инъекция работает. Далее злоумышленник может заменить ELT(8894=8894,1) на подзапрос, например, (SELECT password FROM users LIMIT 1), и извлекать данные посимвольно или целыми строками, если позволяет длина вывода ошибки.

Какие функции MySQL задействованы?

  • EXTRACTVALUE — извлекает значение из XML; при ошибке выводит результат в сообщении.
  • CONCAT — объединяет строки, добавляя маркеры (тильды) для облегчения парсинга.
  • ELT — возвращает элемент по индексу; используется для проверки или подстановки данных.
  • 0x7e — шестнадцатеричное представление символа ~, который часто используется как разделитель, так как редко встречается в обычных данных.

Стоит отметить, что функция EXTRACTVALUE устарела начиная с MySQL 5.6.6 и может быть удалена в будущих версиях. Однако она всё ещё поддерживается во многих установках, что делает её популярной среди злоумышленников.

Чем опасна такая инъекция?

Успешная error-based инъекция позволяет злоумышленнику:

  • Получить доступ к структуре базы данных (имена таблиц, столбцов).
  • Извлечь конфиденциальные данные: логины, пароли (в виде хешей), персональные данные пользователей.
  • В некоторых случаях — выполнить произвольные SQL-запросы, включая изменение или удаление данных.

Даже если приложение не выводит ошибки базы данных напрямую, злоумышленник может использовать слепые методы (boolean-based или time-based), но в данном случае конструкция явно рассчитана на вывод ошибок.

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

Основная причина успешных инъекций — недостаточная фильтрация входных данных и конкатенация их в SQL-запросы. Вот ключевые меры защиты:

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

Также рекомендуется использовать веб-application firewall (WAF), который может блокировать подозрительные запросы, содержащие характерные паттерны вроде EXTRACTVALUE и CONCAT(0x7e.

Заключение

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

Источники