Что такое SQL-инъекция через EXTRACTVALUE?
Представленный запрос %') AND EXTRACTVALUE(1663,CONCAT(0x7e,((SELECT (ELT(1663=1663,1)))),0x7e))-- - — это типичный пример error-based SQL-инъекции (инъекции, основанной на ошибках) для СУБД MySQL. Такие конструкции позволяют злоумышленнику извлекать данные из базы, заставляя сервер возвращать сообщения об ошибках, содержащие результаты подзапросов.
В отличие от UNION-инъекций, где данные выводятся напрямую в ответе приложения, error-based метод использует функцию EXTRACTVALUE для генерации ошибки, текст которой включает интересующую информацию. Это особенно полезно, когда приложение не отображает результаты запроса, но показывает сообщения об ошибках.
Как работает функция EXTRACTVALUE
Функция EXTRACTVALUE(XML_frag, XPath_expr) в MySQL предназначена для извлечения значения из XML-фрагмента по заданному XPath-выражению. Если XPath-выражение некорректно или XML-фрагмент содержит ошибку, функция возвращает сообщение об ошибке, в котором может отображаться часть переданных данных.
Злоумышленники эксплуатируют это свойство: они передают в качестве XML-фрагмента результат подзапроса, а в качестве XPath — заведомо некорректное выражение, чтобы вызвать ошибку с внедрёнными данными.
Разбор конкретного запроса
Рассмотрим запрос по частям:
%')— закрывает предыдущую строку и скобку в уязвимом запросе приложения, подготавливая почву для внедрения.AND EXTRACTVALUE(1663, ...)— вызывает функцию EXTRACTVALUE с произвольным числом 1663 (может быть любым) и вторым аргументом, содержащим полезную нагрузку.CONCAT(0x7e, ((SELECT (ELT(1663=1663,1)))), 0x7e)— формирует строку: символ~(0x7e), результат подзапроса и снова~. Символы тильды используются как маркеры, чтобы облегчить поиск данных в сообщении об ошибке.(SELECT (ELT(1663=1663,1)))— это подзапрос, который возвращает1, если условие1663=1663истинно (а оно всегда истинно). ФункцияELT(N, str1, str2, ...)возвращает N-ю строку из списка. Здесь N=1, поэтому возвращается1. В реальной атаке вместо этого подзапроса мог бы быть, например,(SELECT password FROM users LIMIT 1).-- -— комментарий, который обрезает оставшуюся часть исходного запроса, чтобы не нарушить синтаксис.
В результате выполнения такого запроса MySQL попытается извлечь значение из XML-фрагмента, но поскольку переданная строка не является корректным XML (из-за символов ~), возникнет ошибка вида: XPATH syntax error: '~1~'. В сообщении об ошибке появятся данные, возвращённые подзапросом.
Зачем нужны CONCAT и ELT?
CONCAT объединяет несколько строк в одну. В данном случае он добавляет символы ~ по краям, чтобы облегчить извлечение данных из текста ошибки. Без маркеров было бы сложно понять, где начинается и заканчивается полезная нагрузка.
ELT — это функция, возвращающая N-й элемент из списка строк. В простом примере она возвращает константу 1, но в реальной атаке вместо неё может быть подзапрос, возвращающий конфиденциальные данные (например, имя пользователя, хеш пароля и т.д.).
Комбинация CONCAT и ELT позволяет сформировать строку, которая при попытке обработки как XML вызовет ошибку с внедрёнными данными.
Пример реальной атаки
Предположим, уязвимый запрос выглядит так:
SELECT * FROM articles WHERE id = '$id'
Злоумышленник передаёт в параметр id значение:
1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))-- -
В результате запрос примет вид:
SELECT * FROM articles WHERE id = '1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))-- -'
MySQL выполнит подзапрос SELECT version(), получит, например, 8.0.32, затем попытается обработать строку ~8.0.32~ как XML, что вызовет ошибку: XPATH syntax error: '~8.0.32~'. Эта ошибка будет возвращена приложением, и злоумышленник увидит версию СУБД.
Аналогично можно извлекать имена таблиц, столбцов, логины и пароли пользователей, используя подзапросы с LIMIT и OFFSET для перебора строк.
Меры защиты от error-based SQL-инъекций
Чтобы предотвратить такие атаки, необходимо следовать общим практикам безопасной разработки:
- Использовать параметризованные запросы (prepared statements). Это самый надёжный способ: данные никогда не смешиваются с кодом SQL.
- Экранировать специальные символы. Если по каким-то причинам нельзя использовать подготовленные выражения, применяйте функции экранирования, предоставляемые драйвером БД (например,
mysqli_real_escape_stringв PHP). - Ограничить права пользователя БД. Приложение должно подключаться к базе с минимально необходимыми привилегиями (обычно только SELECT, INSERT, UPDATE, DELETE для нужных таблиц).
- Отключить вывод ошибок СУБД в production. Сообщения об ошибках не должны попадать к конечному пользователю; логируйте их на сервере.
- Использовать WAF (Web Application Firewall). Современные WAF могут обнаруживать и блокировать попытки SQL-инъекций, включая error-based.
- Регулярно проводить аудит кода и пентесты. Это помогает выявлять уязвимости до того, как их обнаружат злоумышленники.
Важно понимать, что error-based инъекции — лишь один из многих методов эксплуатации SQL-инъекций. UNION-based, blind (слепые) и time-based инъекции также широко распространены. Поэтому защита должна быть комплексной.
Заключение
Запрос с EXTRACTVALUE — это классический пример error-based SQL-инъекции, использующей особенности обработки ошибок в MySQL. Понимание механики таких атак помогает разработчикам и специалистам по безопасности эффективнее защищать веб-приложения. Никогда не доверяйте пользовательскому вводу и всегда используйте параметризованные запросы — это золотое правило предотвращает большинство инъекций.
Комментарии
—Войдите, чтобы оставить комментарий