Что такое SQL-инъекция с EXTRACTVALUE?
SQL-инъекция — это один из самых распространённых способов атаки на веб-приложения, при котором злоумышленник внедряет вредоносный SQL-код в запросы к базе данных. Строка, которую вы видите: %")))) AND EXTRACTVALUE(5600,CONCAT(0x7e,((SELECT (ELT(5600=5600,1)))),0x7e))-- - — это не случайный набор символов, а тщательно сконструированная инъекция, использующая особенности функций MySQL для извлечения информации через сообщения об ошибках.
Давайте разберём её по частям.
Структура инъекции
Начнём с начала. Последовательность %")))) — это попытка закрыть существующие кавычки и скобки в оригинальном SQL-запросе, чтобы внедрить свой код. Символ % часто используется в URL-кодировании, но здесь он, вероятно, часть строки. Далее идёт AND EXTRACTVALUE(...) — это условие, которое добавляется к запросу. Если оно истинно, запрос выполняется дальше; если ложно — нет. Но главное — это вызов функции EXTRACTVALUE.
Функция EXTRACTVALUE
EXTRACTVALUE(XML_fragment, XPath_expression) — это функция MySQL (и MariaDB), которая извлекает значение из XML-фрагмента по заданному XPath-выражению. Однако при неправильном использовании она генерирует ошибку, которая может содержать результат вычисления переданного выражения. Именно это и нужно злоумышленнику: заставить базу данных выдать ошибку с полезной информацией.
В нашем случае первый аргумент — 5600. Это просто число, которое не является корректным XML. Второй аргумент — CONCAT(0x7e,((SELECT (ELT(5600=5600,1)))),0x7e). Функция CONCAT объединяет строки. 0x7e — это шестнадцатеричное представление символа ~ (тильда). Он используется как разделитель, чтобы облегчить чтение результата в сообщении об ошибке.
Функция ELT и условие 5600=5600
ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В нашем случае ELT(5600=5600,1). Выражение 5600=5600 всегда истинно, то есть равно 1. Значит, ELT(1,1) вернёт строку '1'. Это простейший пример: инъекция проверяет, что база данных отвечает, и возвращает константу. В реальных атаках вместо 1 может быть подзапрос, извлекающий имя пользователя, хэш пароля и т.д.
Таким образом, CONCAT создаст строку ~1~. Затем EXTRACTVALUE(5600, '~1~') попытается интерпретировать 5600 как XML и применить XPath ~1~. Это вызовет ошибку, в тексте которой будет фигурировать ~1~ — то есть результат нашего подзапроса. Злоумышленник увидит его в ответе сервера.
Зачем нужен -- - в конце?
Двойной дефис -- в SQL — это комментарий до конца строки. Пробел после него и дефис - часто добавляют, чтобы гарантировать, что комментарий будет корректно распознан в разных СУБД. Это позволяет отсечь оставшуюся часть оригинального запроса, которая могла бы помешать выполнению инъекции.
Как это работает на практике
Предположим, уязвимый запрос выглядит так: SELECT * FROM users WHERE id = '$input'. Если передать нашу строку, запрос станет:
SELECT * FROM users WHERE id = '%")))) AND EXTRACTVALUE(5600,CONCAT(0x7e,((SELECT (ELT(5600=5600,1)))),0x7e))-- -'
База данных попытается выполнить это, но из-за синтаксической ошибки в EXTRACTVALUE вернёт сообщение, содержащее ~1~. Если бы вместо 1 стоял подзапрос, например (SELECT password FROM users LIMIT 1), то в ошибке отобразился бы пароль.
Почему это опасно?
Такие инъекции позволяют злоумышленнику извлекать произвольные данные из базы: логины, пароли, номера кредитных карт, персональную информацию. Они могут привести к полной компрометации системы. Особенно опасны слепые инъекции, когда данные извлекаются посимвольно через анализ поведения сервера, но в данном случае используется явная ошибка — это быстрее и проще.
Как защититься?
Основной метод — использование параметризованных запросов (prepared statements). Они разделяют код и данные, поэтому внедрение SQL-кода становится невозможным. Например, в PHP с PDO:
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
$stmt->execute(['id' => $input]);
Дополнительные меры:
- Экранирование специальных символов (но лучше параметризация).
- Ограничение прав пользователя базы данных (не давать прав на чтение системных таблиц).
- Валидация входных данных (например, если ожидается число, проверять, что это число).
- Использование ORM, которые автоматически параметризуют запросы.
- Регулярное обновление СУБД и фреймворков.
Также рекомендуется отключить вывод ошибок базы данных на продакшене, чтобы злоумышленник не мог получить текст ошибки. Вместо этого логируйте ошибки на сервере.
Заключение
Строка %")))) AND EXTRACTVALUE(5600,CONCAT(0x7e,((SELECT (ELT(5600=5600,1)))),0x7e))-- - — это классический пример SQL-инъекции, эксплуатирующей функцию EXTRACTVALUE для извлечения данных через сообщения об ошибках. Понимание механизма таких атак помогает разработчикам лучше защищать свои приложения. Всегда используйте параметризованные запросы и следуйте лучшим практикам безопасности.
Комментарии
—Войдите, чтобы оставить комментарий