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

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

Внешне это выглядит как бессмысленный набор символов, но на самом деле каждый элемент здесь имеет строгое назначение. Давайте разберём её по частям.

Анатомия инъекции

1. Закрытие исходного запроса: "))

В начале строки стоят двойная кавычка и две закрывающие скобки. Это нужно, чтобы «разорвать» оригинальный SQL-запрос, который, вероятно, выглядел примерно так:

SELECT * FROM table WHERE id = ("$input")

Подставив ")), злоумышленник закрывает строковый литерал и вложенные скобки, после чего может добавить собственный код.

2. Логическое условие: AND

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

3. Функция EXTRACTVALUE(8997, CONCAT(...))

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

Злоумышленники используют эту особенность для вывода данных: они формируют такой XPath, который заведомо вызовет ошибку, а в первый аргумент подставляют результат подзапроса. В нашем случае первый аргумент — число 8997, но это не важно; главное — второй аргумент, содержащий CONCAT.

4. Конкатенация с тильдой: CONCAT(0x7e, ..., 0x7e)

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

5. Подзапрос: (SELECT (ELT(8997=8997,1)))

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

6. Комментарий: -- -

Двойной дефис с пробелом — это комментарий в SQL. Он отсекает остаток оригинального запроса, чтобы синтаксис остался корректным. Пробел после -- обязателен в MySQL, иначе комментарий не сработает.

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

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

SELECT * FROM products WHERE category = ("$cat")

Если пользователь передаст в параметр $cat нашу строку, итоговый запрос станет таким:

SELECT * FROM products WHERE category = ("")) AND EXTRACTVALUE(8997,CONCAT(0x7e,((SELECT (ELT(8997=8997,1)))),0x7e))-- -

MySQL попытается выполнить EXTRACTVALUE с некорректным XPath (второй аргумент — строка, начинающаяся с тильды), что вызовет ошибку вида:

XPATH syntax error: '~1~'

В сообщении об ошибке мы увидим ~1~ — это и есть результат подзапроса. Заменив 1 на другой SQL-запрос, злоумышленник может извлечь любые данные: имена таблиц, столбцов, хеши паролей и т.д.

Опасность и последствия

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

  • Читать произвольные данные из базы (конфиденциальная информация, персональные данные пользователей).
  • Обходить аутентификацию, входя в систему под учётной записью администратора.
  • Изменять или удалять данные (если уязвимость позволяет выполнять не только SELECT, но и UPDATE/DELETE).
  • В некоторых случаях — выполнять команды на сервере через LOAD_FILE или INTO OUTFILE.

Именно поэтому подобные строки в логах — тревожный сигнал. Если вы видите их в журналах веб-сервера, значит, ваш сайт пытались взломать.

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

Основной способ борьбы с SQL-инъекциями — использование параметризованных запросов (prepared statements). Они гарантируют, что пользовательские данные никогда не будут интерпретированы как SQL-код. Дополнительные меры:

  1. Экранирование специальных символов с помощью функций вроде mysqli_real_escape_string.
  2. Валидация и фильтрация входных данных (например, ожидание только чисел).
  3. Ограничение прав пользователя базы данных: приложению не нужны права DROP или FILE.
  4. Регулярное обновление СУБД и фреймворков.
  5. Использование WAF (Web Application Firewall) для блокировки подозрительных запросов.

Важно понимать: EXTRACTVALUE — не единственная функция, эксплуатируемая в error-based атаках. Аналогично используются UPDATEXML, GTID_SUBSET, EXP и другие. Однако принцип остаётся тем же: вызвать ошибку, содержащую полезные данные.

Заключение

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

Если вы обнаружили такую строку в логах своего сайта, немедленно проверьте код на наличие незащищённых запросов и внедрите параметризацию. Безопасность базы данных — это не опция, а необходимость.

Источники