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

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

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

Как работает эта инъекция?

Разберём по частям:

  • %")))) — часть строки, которая, вероятно, закрывает предыдущие кавычки и скобки в уязвимом SQL-запросе, чтобы внедрить свой код. Символ % может быть частью URL-кодирования или просто мусором для обхода фильтров.
  • AND EXTRACTVALUE(6806,CONCAT(0x7e,((SELECT (ELT(6806=6806,1)))),0x7e)) — основная полезная нагрузка. Функция EXTRACTVALUE() принимает два аргумента: XML-документ (в данном случае число 6806, которое не является корректным XML) и XPath-выражение. XPath-выражение формируется через CONCAT(), где 0x7e — это шестнадцатеричный код символа ~ (тильда). Внутри XPath выполняется подзапрос SELECT (ELT(6806=6806,1)).
  • ELT(6806=6806,1) — функция ELT() возвращает N-й элемент из списка. Если условие 6806=6806 истинно (что всегда так), то возвращается 1. Это простейший тест, который можно заменить на любой другой подзапрос для извлечения данных, например, версию базы, имя пользователя и т.д.
  • -- - — комментарий, который обрезает оставшуюся часть оригинального SQL-запроса, чтобы не нарушать синтаксис.

Когда MySQL выполняет EXTRACTVALUE(6806, CONCAT(0x7e, (SELECT ...), 0x7e)), он пытается интерпретировать строку, начинающуюся с ~, как XPath. Поскольку это невалидный XPath, возникает ошибка вида: XPATH syntax error: '~1~'. В сообщении об ошибке отображается результат подзапроса (в данном случае «1»). Таким образом, атакующий может извлекать произвольные данные из базы, подставляя вместо ELT(6806=6806,1) другие SQL-выражения.

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

Error-based SQL-инъекции позволяют получать информацию о структуре базы данных, таблицах, полях и содержимом. Например, можно узнать:

  • версию MySQL (SELECT VERSION());
  • имя текущего пользователя базы (SELECT USER());
  • имена таблиц и столбцов через information_schema;
  • логины и пароли пользователей приложения.

Это один из самых опасных типов атак, так как он может привести к полной компрометации базы данных.

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

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

  1. Использование подготовленных выражений (prepared statements). Это самый надёжный способ. Параметризованные запросы отделяют код от данных, и внедрённый SQL-код не выполняется.
  2. Экранирование специальных символов. Если по каким-то причинам нельзя использовать подготовленные выражения, необходимо тщательно экранировать все пользовательские данные с помощью функций вроде mysqli_real_escape_string().
  3. Валидация входных данных. Проверяйте, что вводимые данные соответствуют ожидаемому формату (числа, email и т.д.).
  4. Отключение вывода ошибок базы данных. Сообщения об ошибках не должны показываться пользователю. Логируйте их, но не выводите в браузер.
  5. Использование ORM. Современные ORM (например, Doctrine, Hibernate) обычно используют параметризацию запросов, что снижает риск инъекций.
  6. Регулярное обновление СУБД и фреймворков. Уязвимости в самом MySQL или в библиотеках доступа к данным могут быть использованы.
Важно: даже если приложение не выводит ошибки, error-based инъекция может быть использована «слепым» методом, когда атакующий анализирует время ответа или другие побочные каналы. Поэтому защита должна быть комплексной.

Пример уязвимого кода и его исправление

Рассмотрим простой пример на PHP:

$id = $_GET['id'];
$query = "SELECT * FROM users WHERE id = $id";
$result = mysqli_query($conn, $query);

Если пользователь передаст 1 AND EXTRACTVALUE(6806,CONCAT(0x7e,((SELECT (ELT(6806=6806,1)))),0x7e))-- -, то запрос станет уязвимым. Исправление:

$id = $_GET['id'];
$stmt = $conn->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();

Такой код безопасен, так как параметр $id передаётся отдельно и не интерпретируется как SQL-код.

Заключение

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

Источники