Что такое SQL-инъекция через ExtractValue?
SQL-инъекция — один из самых распространённых способов взлома веб-приложений. Злоумышленник внедряет вредоносный SQL-код в запрос, который затем выполняется на сервере базы данных. Один из изощрённых методов — использование встроенной функции MySQL ExtractValue(). Эта функция предназначена для извлечения значения из XML-документа по заданному XPath-выражению, но при неправильной обработке входных данных она может стать инструментом для извлечения информации из базы.
Запрос, который вы видите в заголовке: "))) AND EXTRACTVALUE(3972,CONCAT(0x7e,((SELECT (ELT(3972=3972,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции. Давайте разберём его по частям.
Как работает функция ExtractValue в MySQL
Синтаксис функции: EXTRACTVALUE(XML_document, XPath_expression). Она возвращает текст из XML-документа, соответствующий XPath-выражению. Если XPath-выражение некорректно, MySQL генерирует ошибку XPATH syntax error, и в тексте ошибки может отображаться часть переданного выражения.
Например, запрос:
SELECT EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e));
вызовет ошибку вида: XPATH syntax error: '~5.7.23~'. Именно этот механизм и эксплуатируют хакеры: они помещают результат подзапроса внутрь XPath-выражения, а затем читают его из сообщения об ошибке, которое возвращается приложению.
Разбор конкретного инъекционного запроса
Рассмотрим строку: "))) AND EXTRACTVALUE(3972,CONCAT(0x7e,((SELECT (ELT(3972=3972,1)))),0x7e))-- -
- "))) — это попытка закрыть ранее открытые скобки и кавычки в исходном SQL-запросе, чтобы внедрить свой код.
- AND EXTRACTVALUE(...) — добавляет условие, которое всегда ложно или истинно, но главное — вызывает выполнение функции ExtractValue.
- 3972 — произвольное число, первый аргумент функции. Может быть любым, так как важен второй аргумент.
- CONCAT(0x7e, ..., 0x7e) — объединяет символ ~ (0x7e) с результатом подзапроса и ещё одним ~. Это делается для того, чтобы отделить выводимые данные в сообщении об ошибке.
- (SELECT (ELT(3972=3972,1))) — подзапрос, который возвращает 1, если условие 3972=3972 истинно. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь условие всегда истинно, поэтому возвращается 1. Это простейшая проверка, но на практике вместо этого подзапроса внедряют извлечение имён таблиц, колонок или хешей паролей.
- -- - — комментарий, который обрезает оставшуюся часть оригинального запроса.
В результате выполнения такого запроса MySQL выдаст ошибку, в тексте которой будет содержаться значение, возвращённое подзапросом (в данном случае «1»), обрамлённое тильдами. Злоумышленник может заменить подзапрос на любой другой, например: (SELECT password FROM users LIMIT 1), и получить пароль в сообщении об ошибке.
Почему это опасно?
Error-based SQL-инъекции через ExtractValue позволяют атакующему:
- Получить версию СУБД, имя базы данных, имена таблиц и колонок.
- Извлечь логины, пароли, номера кредитных карт и другую конфиденциальную информацию.
- В некоторых случаях — выполнить произвольные команды на сервере, если у базы данных есть соответствующие привилегии.
Особенность метода в том, что он не требует вывода данных напрямую на страницу — достаточно, чтобы сообщения об ошибках MySQL отображались пользователю или попадали в логи, к которым есть доступ.
Пример эксплуатации на практике
Предположим, на сайте есть страница с параметром id, который подставляется в запрос без экранирования: SELECT * FROM articles WHERE id = '$id'. Злоумышленник передаёт:
1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e))-- -
Если приложение выводит ошибки MySQL, он увидит что-то вроде: XPATH syntax error: '~mydb~' и узнает имя текущей базы данных. Далее можно перебирать таблицы, колонки и извлекать данные.
Как защититься от SQL-инъекций через ExtractValue
Основной метод защиты — использование подготовленных выражений (prepared statements) с параметризацией запросов. Это исключает возможность внедрения SQL-кода, так как данные передаются отдельно от структуры запроса.
Дополнительные меры:
- Отключите вывод ошибок MySQL в production-окружении. Сообщения об ошибках должны писаться в лог, а не отображаться пользователю.
- Используйте ORM или библиотеки, которые автоматически экранируют входные данные.
- Проводите валидацию всех входных параметров на стороне сервера.
- Ограничьте привилегии пользователя базы данных, от имени которого работает приложение: запретите доступ к системным таблицам, если он не нужен.
- Регулярно обновляйте MySQL и применяйте патчи безопасности.
- Используйте WAF (Web Application Firewall) для фильтрации подозрительных запросов, но помните, что WAF — не панацея.
Заключение
ExtractValue — мощная функция MySQL, но при небрежной обработке пользовательского ввода она превращается в инструмент для кражи данных. Приведённый в запросе пример показывает, как простой подзапрос может быть использован для проверки уязвимости. Если вы разработчик, всегда используйте параметризованные запросы и не показывайте ошибки базы данных конечным пользователям. Если вы администратор — регулярно сканируйте приложения на наличие SQL-инъекций и следите за обновлениями безопасности.
Комментарии
—Войдите, чтобы оставить комментарий