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

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

В данном случае применяются две встроенные функции MySQL: EXTRACTVALUE() и ELT(). Они комбинируются с оператором CONCAT и шестнадцатеричным представлением символа ~ (0x7e). Внешне это выглядит как безобидный набор символов, но на самом деле это попытка заставить сервер выдать скрытые данные.

Разбор компонентов эксплойта

EXTRACTVALUE

EXTRACTVALUE(XML_document, XPath_expression) — функция MySQL, предназначенная для извлечения значения из XML-документа по заданному XPath-выражению. Однако при некорректном XPath-выражении она генерирует ошибку, текст которой содержит переданное выражение. Это и используется в атаках: злоумышленник подставляет в XPath подзапрос, результат которого попадает в сообщение об ошибке.

ELT

ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В нашем случае ELT(6364=6364,1) — это условие, которое всегда истинно (6364=6364), поэтому возвращается первый элемент, то есть число 1. Это простейший тест, который показывает, что инъекция выполняется.

CONCAT и 0x7e

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

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

Два дефиса и пробел (или дефис) в конце строки — это комментарий в SQL, который отсекает оставшуюся часть оригинального запроса. Это стандартный приём, чтобы не нарушать синтаксис.

Закрывающие скобки

Четыре закрывающие скобки )))) в начале нужны для того, чтобы закрыть ранее открытые скобки в уязвимом запросе и встроить свою конструкцию. Количество скобок подбирается экспериментально в зависимости от контекста.

Как работает атака

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

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

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

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

СУБД попытается выполнить EXTRACTVALUE с XPath-выражением, содержащим результат подзапроса. Поскольку это выражение синтаксически некорректно для XPath, MySQL сгенерирует ошибку, в тексте которой будет отображено значение, возвращённое подзапросом. В нашем случае это просто 1, но если вместо ELT(6364=6364,1) подставить, например, (SELECT password FROM users LIMIT 1), то в ошибке появится пароль. Так злоумышленник может пошагово извлекать любые данные из базы.

Этот метод называется error-based SQL-инъекцией, потому что данные извлекаются через сообщения об ошибках. Он особенно опасен, когда приложение выводит ошибки СУБД пользователю. Если же ошибки скрыты, атакующий может использовать слепые методы, но это требует больше времени.

Зачем нужен ELT в этой конструкции?

В конкретном примере ELT(6364=6364,1) — это простейшая проверка на возможность инъекции. Если сервер вернёт ошибку с символом ~1~, значит, уязвимость существует. В реальных атаках вместо этого подзапроса вставляют вызовы функций для извлечения данных, например:

  • ELT(1, (SELECT table_name FROM information_schema.tables LIMIT 1))
  • ELT(1, (SELECT column_name FROM information_schema.columns LIMIT 1))
  • ELT(1, (SELECT password FROM users LIMIT 1))

Таким образом, ELT служит обёрткой, которая позволяет вернуть произвольное значение в контексте, где ожидается число или строка.

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

Если злоумышленнику удаётся эксплуатировать уязвимость, он может:

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

Поэтому важно своевременно выявлять и устранять такие уязвимости.

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

Основной метод защиты — использование параметризованных запросов (prepared statements). В этом случае данные передаются отдельно от SQL-кода, и внедрить произвольные конструкции не получится. Например, в PHP с PDO:

$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
$stmt->execute(['id' => $id]);

Дополнительные меры:

  • Экранирование специальных символов с помощью функций вроде mysqli_real_escape_string() (но это менее надёжно, чем параметризация).
  • Валидация и фильтрация входных данных (например, ожидание только чисел).
  • Ограничение привилегий пользователя БД, от имени которого работает приложение (принцип наименьших привилегий).
  • Отключение вывода подробных ошибок СУБД в production-окружении.
  • Использование ORM и query builder'ов, которые автоматически применяют параметризацию.
  • Регулярное обновление СУБД и фреймворков для устранения известных уязвимостей.

Также рекомендуется проводить аудит кода и использовать сканеры уязвимостей (SAST/DAST), чтобы выявлять потенциальные точки инъекций.

Заключение

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

Источники