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

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

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

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

1. Закрывающие кавычки и скобки: '))

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

SELECT * FROM users WHERE name = ('$input');

Если подставить вместо $input нашу строку, то после подстановки получится:

SELECT * FROM users WHERE name = ('')) AND EXTRACTVALUE(...)-- -');

Двойная закрывающая скобка и апостроф закрывают строковый литерал и скобку, после чего злоумышленник может добавить собственный код.

2. AND — логическое продолжение

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

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

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

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

4. CONCAT и маркеры 0x7e

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

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

Здесь ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Выражение 7928=7928 всегда истинно (1), поэтому ELT(1, 1) вернёт 1. Это простейший тест: если инъекция работает, сервер вернёт ошибку с текстом ~1~. В реальных атаках вместо 1 подставляют имена таблиц, столбцов или другие данные, например: ELT(1, (SELECT table_name FROM information_schema.tables LIMIT 1)).

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

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

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

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

SELECT id, title FROM articles WHERE id = '$id';

Злоумышленник передаёт в параметр id строку:

')) AND EXTRACTVALUE(7928,CONCAT(0x7e,((SELECT (ELT(7928=7928,1)))),0x7e))-- -

После подстановки получается:

SELECT id, title FROM articles WHERE id = '')) AND EXTRACTVALUE(7928,CONCAT(0x7e,((SELECT (ELT(7928=7928,1)))),0x7e))-- -';

Если запрос синтаксически корректен (с учётом закрытия скобок), MySQL выполнит EXTRACTVALUE с некорректным XPath (потому что ~1~ не является валидным XPath). Возникнет ошибка:

ERROR 1105 (HY000): XPATH syntax error: '~1~'

В тексте ошибки мы видим ~1~ — это результат выполнения подзапроса. Если вместо 1 подставить, например, (SELECT version()), то в ошибке отобразится версия MySQL. Так злоумышленник может извлекать произвольные данные.

Зачем это нужно злоумышленнику?

  • Разведка: проверить, уязвим ли сайт к SQL-инъекциям.
  • Извлечение данных: получить имена таблиц, столбцов, логины, пароли и другую конфиденциальную информацию.
  • Обход аутентификации: иногда такие инъекции позволяют войти в систему без пароля.
  • Компрометация сервера: в тяжёлых случаях — выполнение произвольных команд.

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

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

  • Использовать ORM (например, Hibernate, Entity Framework) с правильной настройкой.
  • Экранировать все пользовательские данные с помощью функций экранирования, специфичных для СУБД.
  • Ограничить права пользователя базы данных: не давать ему доступ к information_schema без необходимости.
  • Включить логирование ошибок СУБД, но не показывать их пользователю — это усложняет эксплуатацию error-based инъекций.
  • Регулярно проводить сканирование уязвимостей и обновлять ПО.

Важно понимать: даже если сайт не использует MySQL, аналогичные техники существуют и для других СУБД (PostgreSQL, MS SQL, Oracle). Поэтому универсальная рекомендация — никогда не доверять пользовательскому вводу и всегда использовать параметризацию.

Что делать, если вы нашли такую строку в логах?

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

  1. Уязвим ли ваш код к SQL-инъекциям (проведите аудит).
  2. Не произошло ли утечки данных (проверьте логи доступа к базе).
  3. Обновите CMS и плагины до последних версий.
  4. Установите WAF (Web Application Firewall), который может блокировать подобные запросы.

Помните, что ошибки в логах — это не всегда успешная атака, но всегда повод для проверки.

Источники