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

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

SQL-инъекция — один из самых распространённых способов взлома веб-приложений. Злоумышленник внедряет в пользовательский ввод специальные конструкции, которые изменяют логику SQL-запроса. Error-based инъекция — это разновидность, при которой атакующий заставляет базу данных вернуть сообщение об ошибке, содержащее полезные данные (например, версию СУБД, имена таблиц, хеши паролей).

В отличие от blind-инъекций, где информация извлекается по косвенным признакам (истина/ложь, задержки), error-based даёт мгновенный результат — текст ошибки с внедрёнными данными. Это делает её очень эффективной при наличии соответствующей уязвимости.

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

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

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

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

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

SELECT * FROM articles WHERE id = '$id';

Если переменная $id не фильтруется, атакующий может передать:

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

В результате итоговый SQL-запрос станет:

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

MySQL попытается выполнить функцию EXTRACTVALUE с аргументом CONCAT(0x7e, (SELECT ...), 0x7e). Поскольку XPath-выражение начинается с символа ~, что недопустимо, СУБД сгенерирует ошибку:

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

В сообщении об ошибке появится результат подзапроса — в данном случае «1». В реальной атаке вместо «1» будет, например, версия MySQL или хеш пароля.

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

Функция EXTRACTVALUE появилась в MySQL 5.1. Она предназначена для работы с XML, но из-за особенности вывода ошибок стала популярным инструментом для error-based инъекций. Аналогично используются UPDATEXML и XMLTYPE (в Oracle).

Функция ELT — это сокращение от «Element». Она возвращает N-й элемент из списка строк. В контексте инъекции её применяют для того, чтобы вернуть конкретное значение (например, результат подзапроса) в виде строки, которую затем можно передать в EXTRACTVALUE.

Комбинация ELT(2958=2958,1) — это простейший тест: если выражение истинно, возвращается «1». В более сложных атаках вместо «1» подставляют подзапрос, например: ELT(1,(SELECT version())).

Последствия успешной атаки

Если злоумышленник может выполнить такую инъекцию, он получает доступ к произвольным данным в базе:

  • чтение конфиденциальной информации (логины, пароли, персональные данные);
  • изменение или удаление записей;
  • получение полного контроля над сервером БД в некоторых конфигурациях.

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

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

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

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

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

Заключение

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

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

Источники