Что такое SQL-инъекция через EXTRACTVALUE?
SQL-инъекция — это один из самых распространённых способов взлома веб-приложений, при котором злоумышленник внедряет вредоносный SQL-код в запрос к базе данных. Запрос, который вы видите — " AND EXTRACTVALUE(3798,CONCAT(0x7e,((SELECT (ELT(3798=3798,1)))),0x7e))-- - — является классическим примером так называемой error-based SQL-инъекции (инъекция, основанная на ошибках). Она нацелена на СУБД MySQL и использует функцию EXTRACTVALUE() для принудительного вывода данных через сообщение об ошибке.
Главная цель такой инъекции — заставить сервер базы данных вернуть в ответе на запрос ту информацию, которую атакующий хочет получить: версию MySQL, имя текущей базы данных, имена таблиц, логины и пароли пользователей. Поскольку напрямую вывести эти данные в HTML-ответ часто невозможно, злоумышленники прибегают к трюкам с генерацией ошибок, которые затем отображаются на странице.
Разбор структуры вредоносного запроса
Давайте разберём строку по частям, чтобы понять логику атакующего.
"— закрывающая кавычка. Она нужна, чтобы «разорвать» исходный SQL-запрос и добавить свой код. В уязвимом приложении строка могла выглядеть так:SELECT * FROM products WHERE name = "$input". Подставив кавычку, атакующий закрывает строковый литерал и получает возможность дописать собственные инструкции.AND— логический оператор. Он присоединяет условие к оригинальному запросу, чтобы тот оставался синтаксически корректным.EXTRACTVALUE(3798, CONCAT(...))— вызов функции MySQL.EXTRACTVALUE(XML_fragment, XPath_expression)извлекает значение из XML-фрагмента по заданному XPath-выражению. Если XPath-выражение некорректно, MySQL генерирует ошибку и включает в текст ошибки переданное значение. Именно это и эксплуатируется.CONCAT(0x7e, ((SELECT (ELT(3798=3798,1)))), 0x7e)— конкатенация.0x7e— это шестнадцатеричное представление символа~(тильда). Тильда используется как маркер, чтобы в сообщении об ошибке легко было найти начало и конец выводимых данных. Внутри — подзапросSELECT (ELT(3798=3798,1)).ELT(N, str1, str2, ...)— функция, возвращающая N-й элемент из списка строк. Выражение3798=3798всегда истинно (равно 1), поэтомуELT(1, 1)вернёт строку'1'. В реальной атаке вместо1подставляется подзапрос, извлекающий нужные данные, например:ELT(1, (SELECT password FROM users LIMIT 1)).-- -— комментарий. Два дефиса с пробелом (или дефис-дефис-пробел) в MySQL означают начало комментария до конца строки. Это позволяет «отрезать» оставшуюся часть оригинального запроса, чтобы он не вызвал синтаксическую ошибку.
В результате MySQL пытается выполнить EXTRACTVALUE(3798, '~1~'). Поскольку '~1~' не является корректным XPath-выражением, СУБД возвращает ошибку вида: XPATH syntax error: '~1~'. Атакующий видит эту ошибку на странице и понимает, что инъекция работает. Далее он заменяет 1 на подзапросы, чтобы извлечь реальные данные.
Почему EXTRACTVALUE, а не UNION?
Метод UNION SELECT тоже популярен, но у него есть ограничения. Чтобы он сработал, нужно точно знать количество столбцов в оригинальном запросе и их типы. Кроме того, не всегда вывод UNION-запроса отображается на странице. Error-based инъекция через EXTRACTVALUE() не требует знания структуры SELECT и работает даже тогда, когда результаты обычного запроса не выводятся. Достаточно, чтобы приложение показывало сообщения об ошибках базы данных (что само по себе является плохой практикой).
Важно: начиная с MySQL 5.7 функция EXTRACTVALUE() была объявлена устаревшей, а в MySQL 8.0 — удалена. Однако многие сайты до сих пор работают на старых версиях, поэтому угроза остаётся актуальной.
Какие данные можно извлечь?
С помощью этой техники атакующий может получить практически любую информацию из базы:
- версию MySQL (
SELECT version()); - имя текущей базы данных (
SELECT database()); - список таблиц (
SELECT table_name FROM information_schema.tables); - имена столбцов;
- учётные данные пользователей (логины, хеши паролей);
- персональные данные клиентов.
Поскольку длина вывода в сообщении об ошибке ограничена (обычно около 32 символов), злоумышленники используют функции SUBSTRING() или MID(), чтобы извлекать данные по частям.
Как защититься от SQL-инъекций
Основной способ защиты — использовать параметризованные запросы (prepared statements). В этом случае данные пользователя передаются отдельно от SQL-кода и не могут изменить структуру запроса. Дополнительные меры:
- Никогда не выводить сообщения об ошибках базы данных конечному пользователю — только в лог-файлы.
- Использовать ORM и проверенные библиотеки для работы с БД.
- Ограничить права пользователя базы данных: приложению не нужны права на чтение
information_schemaили удаление таблиц. - Регулярно обновлять СУБД и фреймворки.
- Применять WAF (Web Application Firewall) для блокировки подозрительных запросов.
Если вы встретили подобную строку в логах своего сайта — это сигнал о попытке взлома. Срочно проверьте код на наличие уязвимостей и закройте доступ к сообщениям об ошибках.
Комментарии
—Войдите, чтобы оставить комментарий