Что такое SQL-инъекция через ExtractValue?
SQL-инъекция — один из самых распространённых способов взлома веб-приложений. Злоумышленник внедряет в пользовательский ввод специальные конструкции, которые меняют логику SQL-запроса. В данном случае рассматривается полезная нагрузка, использующая функцию ExtractValue — инструмент MySQL для работы с XML. Эта функция часто применяется в так называемых error-based инъекциях, когда атакующий заставляет базу данных выдать сообщение об ошибке, содержащее конфиденциальные данные.
Конкретный запрос: ' OR EXTRACTVALUE(6351,CONCAT(0x7e,((SELECT (ELT(6351=6351,1)))),0x7e))-- - — типичный пример такой атаки. Давайте разберём его по частям.
Анатомия полезной нагрузки
Начнём с начала строки. Символ ' закрывает строковый литерал в исходном запросе, после чего добавляется OR. Это позволяет обойти проверку условия и выполнить внедрённый код. Далее идёт вызов EXTRACTVALUE(6351, CONCAT(0x7e, ..., 0x7e)).
ExtractValue принимает два аргумента: XML-документ и XPath-выражение. Если первый аргумент не является корректным XML, MySQL выдаёт ошибку, в которой отображается переданное XPath-выражение. Именно это и нужно атакующему — заставить базу данных вывести результат подзапроса в тексте ошибки.
Первый аргумент — 6351 — просто число, которое не является XML, поэтому ошибка гарантирована. Второй аргумент — CONCAT(0x7e, ((SELECT (ELT(6351=6351,1)))), 0x7e) — конструирует строку, которая попадёт в сообщение об ошибке.
Роль CONCAT и шестнадцатеричных литералов
0x7e — это шестнадцатеричное представление символа ~ (тильда). Тильды используются как маркеры, чтобы атакующий мог легко найти внедрённые данные в длинном тексте ошибки. CONCAT объединяет тильду, результат подзапроса и ещё одну тильду.
Подзапрос ((SELECT (ELT(6351=6351,1)))) — это сердце атаки. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь N — это выражение 6351=6351, которое всегда истинно (равно 1). Следовательно, ELT(1, 1) вернёт первый элемент — число 1. В реальной атаке вместо 1 могло бы быть имя пользователя, пароль или другая敏感 информация, полученная через подзапрос, например SELECT password FROM users LIMIT 1.
В нашем примере подзапрос возвращает просто 1, что демонстрирует работоспособность техники. Злоумышленник проверяет, уязвим ли сайт, и если да, то заменяет константу на извлечение данных.
Завершающая часть: -- -
Комментарий -- - (дефис-дефис-пробел) отсекает остаток оригинального SQL-запроса. Это стандартный приём, чтобы не нарушать синтаксис. В некоторых СУБД требуется пробел после двух дефисов, поэтому часто пишут -- - или #.
Почему это работает?
Уязвимость возникает, когда приложение не фильтрует пользовательский ввод и подставляет его напрямую в SQL-запрос. Например, код на PHP может выглядеть так:
$query = "SELECT * FROM articles WHERE id = '" . $_GET['id'] . "'";
Если передать в параметр id нашу полезную нагрузку, запрос превратится в:
SELECT * FROM articles WHERE id = '' OR EXTRACTVALUE(6351,CONCAT(0x7e,((SELECT (ELT(6351=6351,1)))),0x7e))-- -'
База данных выполнит EXTRACTVALUE, что приведёт к ошибке с текстом, содержащим результат подзапроса. Ошибка обычно отображается на странице или попадает в логи, откуда атакующий её извлекает.
Какие данные можно получить?
С помощью этой техники злоумышленник может извлечь любые данные, к которым имеет доступ уязвимый запрос: имена пользователей, хеши паролей, номера кредитных карт, персональные данные клиентов. Всё зависит от привилегий учётной записи, от имени которой выполняется запрос. Если это администратор БД, то под угрозой вся база.
Как защититься от SQL-инъекций?
Основной метод — использование параметризованных запросов (prepared statements). Они разделяют код и данные, поэтому ввод пользователя никогда не интерпретируется как SQL-код.
- Параметризация запросов — самый надёжный способ. В PHP это PDO или mysqli с подготовленными выражениями.
- Экранирование специальных символов — вспомогательная мера, но не панацея.
- Валидация входных данных — проверяйте, что идентификаторы являются числами, строки не содержат опасных символов.
- Ограничение прав СУБД — не используйте учётную запись с правами администратора для работы приложения.
- Отключение вывода ошибок — в production-окружении ошибки не должны показываться пользователю.
- Использование WAF — веб-приложения-фаерволы могут блокировать известные сигнатуры атак.
Также рекомендуется регулярно обновлять СУБД и фреймворки, проводить аудит кода и пентесты.
Заключение
Запрос ' OR EXTRACTVALUE(6351,CONCAT(0x7e,((SELECT (ELT(6351=6351,1)))),0x7e))-- - — это классическая error-based SQL-инъекция, эксплуатирующая функцию ExtractValue в MySQL. Понимание таких атак помогает разработчикам и специалистам по безопасности лучше защищать свои системы. Никогда не доверяйте пользовательскому вводу и всегда используйте параметризованные запросы.
Комментарии
—Войдите, чтобы оставить комментарий