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

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

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

Как работает error-based SQL-инъекция

Error-based инъекция — это метод, при котором атакующий заставляет СУБД сгенерировать ошибку, содержащую полезные данные. В MySQL для этого часто используют функции EXTRACTVALUE или UPDATEXML. Они предназначены для работы с XML, но при передаче некорректного XPath-выражения возвращают ошибку, в тексте которой отображается переданная строка.

В нашем примере:

  • EXTRACTVALUE(7919, CONCAT(0x7e, ...)) — функция пытается извлечь значение из XML-документа (первый аргумент — случайное число, которое не является XML).
  • CONCAT(0x7e, ..., 0x7e) — объединяет символ ~ (0x7e) с результатом подзапроса и ещё одним ~.
  • (SELECT (ELT(7919=7919,1))) — подзапрос, который возвращает 1, если условие 7919=7919 истинно. Функция ELT выбирает N-й элемент из списка; здесь список состоит из одного элемента 1.

В результате MySQL выдаёт ошибку вида: XPATH syntax error: '~1~'. Если вместо 1 подставить подзапрос, извлекающий имя пользователя или хеш пароля, эти данные окажутся в сообщении об ошибке.

Зачем нужны ELT и CONCAT?

ELT(N, str1, str2, ...) возвращает строку под номером N. В нашем случае N — это результат сравнения 7919=7919, то есть 1 (истина). Это простейший способ вернуть конкретное значение. В реальных атаках вместо 1 подставляют подзапросы, например (SELECT database()) или (SELECT password FROM users LIMIT 1).

CONCAT нужен, чтобы обернуть результат символами ~. Это делает вывод ошибки более читаемым: всё, что находится между тильдами, — это извлечённые данные. Без разделителей границы значения были бы неясны.

Важно: error-based инъекция работает только если приложение выводит сообщения об ошибках СУБД пользователю. В production-средах эту информацию обычно скрывают, что затрудняет эксплуатацию.

Пример эксплуатации

Предположим, есть уязвимый параметр id в URL: https://example.com/product?id=1. Атакующий подставляет:

1")))) AND EXTRACTVALUE(7919,CONCAT(0x7e,((SELECT (ELT(7919=7919,1)))),0x7e))-- -

Если приложение уязвимо, сервер вернёт ошибку с текстом ~1~. Затем вместо 1 можно подставить (SELECT version()) и получить версию MySQL. Далее — имена таблиц, столбцов и сами данные.

Символы ")))) в начале нужны, чтобы закрыть предыдущие кавычки и скобки в исходном запросе, а -- - — это комментарий, который отсекает оставшуюся часть оригинального SQL-запроса.

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

Основной метод защиты — параметризованные запросы (prepared statements). Они разделяют код и данные, поэтому внедрённый SQL никогда не выполнится. Дополнительные меры:

  • Валидация и фильтрация всех входных данных (белые списки).
  • Отключение вывода ошибок СУБД в production.
  • Использование ORM и современных фреймворков.
  • Регулярное обновление СУБД и веб-приложений.
  • WAF (Web Application Firewall) для блокировки подозрительных запросов.

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

Заключение

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