Строка %') OR EXTRACTVALUE(1492,CONCAT(0x7e,((SELECT (ELT(1492=1492,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции (инъекции на основе ошибок) для СУБД MySQL. Такие конструкции используют для извлечения данных из базы через сообщения об ошибках, которые возвращает сервер. В этой статье мы разберём, как работает этот запрос, зачем нужна функция EXTRACTVALUE и как защититься от подобных атак.
Что такое error-based SQL-инъекция?
SQL-инъекция — один из самых распространённых способов взлома веб-приложений. Злоумышленник внедряет вредоносный SQL-код в параметры запроса, которые приложение передаёт в базу данных. Если приложение не фильтрует входные данные, база выполняет команды атакующего.
Error-based инъекция — это техника, при которой хакер заставляет базу данных выдать конфиденциальную информацию прямо в тексте ошибки. MySQL в некоторых случаях возвращает детализированные сообщения об ошибках, которые могут содержать имена таблиц, колонок или даже данные. Функция EXTRACTVALUE — один из инструментов для такого извлечения.
Разбор строки инъекции
Давайте посмотрим на запрос по частям:
%')— попытка закрыть предыдущее выражение в уязвимом запросе. Символ%часто используется в LIKE-запросах, а')закрывает скобку и кавычку.OR EXTRACTVALUE(1492,CONCAT(0x7e,((SELECT (ELT(1492=1492,1)))),0x7e))— основная полезная нагрузка. ФункцияEXTRACTVALUEизвлекает значение из XML-строки. Если переданный XML некорректен, MySQL выдаёт ошибку, в которой отображается переданный фрагмент.-- -— комментарий, который отсекает остаток оригинального запроса.
Внутри EXTRACTVALUE используется CONCAT для объединения тильды (0x7e), результата подзапроса и ещё одной тильды. Тильды служат маркерами, чтобы в сообщении об ошибке легко было найти нужные данные. Подзапрос SELECT (ELT(1492=1492,1)) — это простейшая проверка: ELT возвращает строку по номеру. Здесь 1492=1492 всегда истинно (1), поэтому возвращается 1. В реальной атаке вместо этой заглушки подставляют вызовы вроде (SELECT user()) или (SELECT password FROM users LIMIT 1).
Как работает EXTRACTVALUE?
Функция EXTRACTVALUE(XML_document, XPath_expression) появилась в MySQL 5.1. Она извлекает значение из XML-документа по заданному XPath-выражению. Если XPath-выражение некорректно, MySQL генерирует ошибку вида:
XPATH syntax error: '~данные~'
Именно эти «данные» и являются целью атакующего. Передавая в XPath-выражение результат подзапроса, хакер может вытащить любую информацию: версию базы, имя пользователя, хеши паролей и т.д.
Пример более реалистичной инъекции:
' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))-- -
В ответе сервер вернёт ошибку с версией MySQL, например: XPATH syntax error: '~5.7.33~'.
Пошаговый пример атаки
Предположим, уязвимый запрос выглядит так:
SELECT * FROM articles WHERE id = '%') OR EXTRACTVALUE(1492,CONCAT(0x7e,((SELECT (ELT(1492=1492,1)))),0x7e))-- -'
После подстановки база выполнит:
- Закроет условие
id = '%'. - Вычислит
EXTRACTVALUE. Поскольку второй аргумент — невалидный XPath (содержит тильды и результат подзапроса), возникнет ошибка. - В тексте ошибки отобразится переданная строка, включая результат подзапроса.
Атакующий может менять подзапрос, чтобы извлекать данные посимвольно или целыми строками. Например, для получения имени пользователя базы:
' OR EXTRACTVALUE(1, CONCAT(0x7e, (SELECT user()), 0x7e))-- -
Ответ: XPATH syntax error: '~root@localhost~'.
Какие данные можно украсть?
С помощью error-based инъекции через EXTRACTVALUE злоумышленник может получить:
- Версию СУБД и операционной системы.
- Имя текущего пользователя базы данных.
- Имена таблиц и колонок из
information_schema. - Логины и пароли пользователей приложения (часто в хешированном виде).
- Персональные данные клиентов: ФИО, телефоны, email, адреса.
- Данные банковских карт, если они хранятся в базе (что само по себе нарушение PCI DSS).
Получив доступ к базе, атакующий может не только читать, но и изменять или удалять данные, а также использовать SQL-инъекцию для выполнения команд на сервере (при наличии соответствующих привилегий).
Как защититься от SQL-инъекций?
Основной метод защиты — параметризованные запросы (prepared statements). Они разделяют код и данные, поэтому внедрённый SQL-код не выполняется. Например, в PHP с PDO:
$stmt = $pdo->prepare('SELECT * FROM articles WHERE id = :id');
$stmt->execute(['id' => $id]);
Дополнительные меры:
- Использовать ORM (Doctrine, Hibernate, Entity Framework), которые автоматически экранируют параметры.
- Валидировать и фильтровать все входные данные на стороне сервера.
- Ограничить права пользователя базы данных: приложению не нужны права
FILE,DROPили доступ кinformation_schemaбез необходимости. - Отключить вывод подробных ошибок MySQL в production-окружении. Вместо этого логировать их на сервере.
- Регулярно обновлять СУБД и фреймворки, чтобы закрыть известные уязвимости.
- Использовать WAF (Web Application Firewall) для блокировки подозрительных запросов.
Заключение
Строка %') OR EXTRACTVALUE(1492,CONCAT(0x7e,((SELECT (ELT(1492=1492,1)))),0x7e))-- - — это не просто набор символов, а рабочий инструмент хакера для эксплуатации error-based SQL-инъекций в MySQL. Понимание принципов работы таких атак помогает разработчикам и администраторам своевременно закрывать уязвимости и защищать данные пользователей. Помните: безопасность — это процесс, а не одноразовое действие.
Комментарии
—Войдите, чтобы оставить комментарий