Что это за строка?
Строка %")))) 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-инъекций?
Основные меры защиты:
- Использование подготовленных выражений (prepared statements). Это самый надёжный способ. Параметризованные запросы отделяют код от данных, и внедрённый SQL-код не выполняется.
- Экранирование специальных символов. Если по каким-то причинам нельзя использовать подготовленные выражения, необходимо тщательно экранировать все пользовательские данные с помощью функций вроде
mysqli_real_escape_string(). - Валидация входных данных. Проверяйте, что вводимые данные соответствуют ожидаемому формату (числа, email и т.д.).
- Отключение вывода ошибок базы данных. Сообщения об ошибках не должны показываться пользователю. Логируйте их, но не выводите в браузер.
- Использование ORM. Современные ORM (например, Doctrine, Hibernate) обычно используют параметризацию запросов, что снижает риск инъекций.
- Регулярное обновление СУБД и фреймворков. Уязвимости в самом 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. Понимание механизма таких атак помогает разработчикам и специалистам по безопасности правильно защищать веб-приложения. Всегда используйте подготовленные выражения и никогда не доверяйте пользовательскому вводу.
Комментарии
—Войдите, чтобы оставить комментарий