Введение

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

В этой статье мы детально разберём, из чего состоит данный запрос, как он работает, какие функции MySQL задействованы и как защититься от подобных атак.

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

SQL-инъекция — это один из самых распространённых способов атаки на веб-приложения. Злоумышленник внедряет в пользовательский ввод специальные конструкции, которые меняют логику SQL-запроса. При error-based инъекции атакующий заставляет базу данных сгенерировать ошибку, в тексте которой содержатся полезные данные: имена таблиц, колонок, логины, пароли и т.д.

MySQL при определённых условиях возвращает подробные сообщения об ошибках, которые могут быть видны в ответе сервера. Это и позволяет извлекать информацию посимвольно или целыми строками.

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

Рассмотрим каждый элемент запроса:

  • ` — обратный апостроф (бэктик). В MySQL используется для экранирования имён идентификаторов (таблиц, колонок). В начале строки он, скорее всего, закрывает ранее открытый бэктик в уязвимом запросе.
  • AND — логический оператор, который добавляется к условию WHERE. Он позволяет внедрить дополнительное выражение, не нарушая синтаксис исходного запроса.
  • EXTRACTVALUE(5312, CONCAT(...)) — функция MySQL, предназначенная для извлечения значения из XML-строки. Она принимает два аргумента: XML-документ и XPath-выражение. Если XPath-выражение некорректно, функция возвращает ошибку. Именно эту ошибку использует атакующий.
  • 5312 — произвольное число, которое передаётся как XML-документ. Оно не является валидным XML, что уже может вызвать ошибку, но главное — второй аргумент.
  • CONCAT(0x7e, ..., 0x7e) — функция конкатенации строк. Она объединяет символы в одну строку. 0x7e — это шестнадцатеричный код символа ~ (тильда). Тильда используется как маркер, чтобы в сообщении об ошибке было легко найти границы извлечённых данных.
  • (SELECT (ELT(5312=5312,1))) — подзапрос, который возвращает результат функции ELT. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь условие 5312=5312 всегда истинно, поэтому ELT возвращает 1 (первый элемент). Это простейший пример; в реальной атаке вместо 1 может быть подзапрос, извлекающий данные, например (SELECT password FROM users LIMIT 1).
  • -- - — комментарий в MySQL. Всё, что идёт после него, игнорируется. Это нужно, чтобы обрезать остаток оригинального запроса, который мог бы вызвать синтаксическую ошибку.

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

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

SELECT * FROM articles WHERE id = '1'

Злоумышленник подставляет вместо 1 строку 1` AND EXTRACTVALUE(5312,CONCAT(0x7e,((SELECT (ELT(5312=5312,1)))),0x7e))-- -. В результате запрос принимает вид:

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

MySQL выполняет функцию EXTRACTVALUE. Поскольку второй аргумент (XPath) содержит символ ~, который недопустим в XPath, возникает ошибка. В тексте ошибки MySQL выводит переданную строку, например:

XPATH syntax error: '~1~'

Таким образом, атакующий видит результат выполнения подзапроса. В данном примере это просто «1», но если вместо ELT(5312=5312,1) подставить, скажем, (SELECT version()), в ошибке отобразится версия MySQL. Это и есть извлечение данных.

Зачем нужны 0x7e и ELT

Символ ~ (0x7e) выбран не случайно: он редко встречается в обычных данных и легко заметен в сообщении об ошибке. Он служит разделителем, чтобы точно определить начало и конец извлечённой строки.

Функция ELT позволяет возвращать конкретную строку из списка в зависимости от условия. В простейшем случае условие всегда истинно, и возвращается первый элемент. В более сложных атаках ELT может использоваться для побитового извлечения данных: например, сравнивая символы и возвращая разные значения в зависимости от результата.

Какие данные можно извлечь

С помощью error-based инъекций через EXTRACTVALUE злоумышленник может получить:

  • версию СУБД;
  • имя текущей базы данных;
  • имена таблиц и колонок;
  • содержимое таблиц (логины, пароли, персональные данные).

Всё это становится возможным, если приложение не фильтрует пользовательский ввод и выводит ошибки базы данных на страницу.

Как защититься

Основные меры защиты от SQL-инъекций, включая error-based:

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

Заключение

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

Источники