Введение

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

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

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

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

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

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

1. AND

Оператор AND используется для добавления условия к существующему SQL-запросу. Например, если исходный запрос был SELECT * FROM users WHERE id = 1, то после внедрения он может стать SELECT * FROM users WHERE id = 1 AND EXTRACTVALUE(...). Это позволяет выполнить внедрённую функцию только в том случае, если исходное условие истинно, что не нарушает логику запроса, но добавляет выполнение вредоносного кода.

2. EXTRACTVALUE(6050, CONCAT(...))

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

В нашем случае первым аргументом идёт число 6050 — это просто произвольное число, которое не несёт смысловой нагрузки (может быть любым). Второй аргумент — CONCAT(0x7e, ((SELECT (ELT(6050=6050,1)))), 0x7e).

3. CONCAT(0x7e, ..., 0x7e)

Функция CONCAT() объединяет строки. Здесь она склеивает символ 0x7e (это шестнадцатеричное представление символа ~ — тильда), затем результат подзапроса и снова тильду. Тильда используется как маркер, чтобы в сообщении об ошибке легко было найти извлечённые данные: они будут заключены между двумя тильдами. Например, ошибка может выглядеть так: XPATH syntax error: '~1~'.

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

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

5. -- -

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

Как работает атака целиком

Предположим, веб-приложение выполняет запрос:
SELECT * FROM products WHERE id = 1 AND EXTRACTVALUE(6050,CONCAT(0x7e,((SELECT (ELT(6050=6050,1)))),0x7e))-- -

База данных выполняет:

  1. Вычисляет 6050=6050 → истина (1).
  2. Вычисляет ELT(1,1) → строка '1'.
  3. Формирует строку CONCAT('~', '1', '~') → '~1~'.
  4. Передаёт '~1~' в EXTRACTVALUE(6050, '~1~').
  5. Поскольку '~1~' не является корректным XPath, MySQL генерирует ошибку: XPATH syntax error: '~1~'.
  6. Эта ошибка возвращается в ответе приложения (если вывод ошибок не отключён).

Злоумышленник видит в ответе '~1~' и понимает, что инъекция работает. Далее он может заменить ELT(6050=6050,1) на подзапрос, извлекающий нужные данные, например: (SELECT password FROM users LIMIT 1). Тогда в ошибке отобразится хеш пароля.

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

Error-based SQL-инъекции позволяют злоумышленнику:

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

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

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

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

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

Заключение

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

Источники