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