Что такое SQL-инъекция через ExtractValue?
SQL-инъекция — один из самых распространённых способов атаки на веб-приложения, при котором злоумышленник внедряет вредоносный SQL-код в запросы к базе данных. Особый интерес представляет техника, основанная на функции ExtractValue в СУБД MySQL. Эта функция изначально предназначена для извлечения значения из XML-документа по указанному пути XPath. Однако при неправильной обработке ошибок она может стать каналом утечки конфиденциальной информации.
В запросе, который нас интересует, используется следующая конструкция:
' OR EXTRACTVALUE(2989,CONCAT(0x7e,((SELECT (ELT(2989=2989,1)))),0x7e))-- -
Давайте разберём её по частям и поймём, как она работает и какую цель преследует.
Детальный разбор внедрённого кода
Начнём с начала строки: ' OR .... Одинарная кавычка закрывает предполагаемое строковое значение в уязвимом параметре. Затем оператор OR добавляет логическое условие, которое всегда истинно (если правая часть вернёт истину), что позволяет обойти аутентификацию или изменить логику запроса. Далее вызывается функция EXTRACTVALUE(2989, CONCAT(...)).
Первый аргумент — число 2989 — это произвольный XML-фрагмент, который не несёт смысловой нагрузки, но должен быть валидным для функции. Второй аргумент — результат CONCAT(0x7e, ((SELECT (ELT(2989=2989,1)))), 0x7e). Здесь 0x7e — это шестнадцатеричное представление символа тильды (~). Он используется как разделитель, чтобы облегчить извлечение данных из сообщения об ошибке.
Внутри CONCAT выполняется подзапрос SELECT (ELT(2989=2989,1)). Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае условие 2989=2989 всегда истинно, что даёт 1, а значит, ELT(1, 1) вернёт строку '1'. Это тривиальный пример, но на месте '1' может быть любой другой подзапрос, извлекающий данные (например, имя пользователя, хеш пароля и т.д.).
Ключевой момент: EXTRACTVALUE ожидает, что второй аргумент будет корректным XPath-выражением. Если это не так, MySQL генерирует ошибку, в тексте которой отображается переданное значение. Таким образом, злоумышленник может заставить базу данных вывести нужные данные в сообщении об ошибке, которое затем отобразится на странице (если приложение не подавляет ошибки).
Завершающая часть -- - — это комментарий, который отсекает оставшуюся часть оригинального SQL-запроса, чтобы не возникло синтаксической ошибки.
Как работает атака на практике
Предположим, на сайте есть форма входа, и параметр username подставляется в запрос без экранирования. Злоумышленник вводит в поле логина строку, подобную приведённой. В результате SQL-запрос принимает вид:
SELECT * FROM users WHERE username = '' OR EXTRACTVALUE(2989,CONCAT(0x7e,((SELECT (ELT(2989=2989,1)))),0x7e))-- -' AND password = '...';
СУБД выполняет EXTRACTVALUE, терпит неудачу из-за неверного XPath и возвращает ошибку вида:
XPATH syntax error: '~1~'
В этом сообщении между тильдами отображается результат подзапроса. Заменив '1' на другой SQL-запрос, например (SELECT version()), атакующий получит версию MySQL. Аналогично можно извлечь имена таблиц, колонок и даже хеши паролей.
Этот метод относится к классу error-based SQL injection (SQL-инъекция на основе ошибок). Его преимущество для злоумышленника в том, что не требуется слепое угадывание (boolean-based) или задержки (time-based) — данные возвращаются напрямую в ответе сервера.
Примеры полезных нагрузок
Вот несколько вариаций, которые могут использоваться для извлечения информации:
' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e))-- -— получение имени текущей базы данных.' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT user()), 0x7e))-- -— получение имени пользователя БД.' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT table_name FROM information_schema.tables LIMIT 0,1), 0x7e))-- -— извлечение первой таблицы из схемы.
Обратите внимание, что в некоторых случаях вместо EXTRACTVALUE может использоваться аналогичная функция UPDATEXML, которая также генерирует ошибки с внедрёнными данными.
Меры защиты от SQL-инъекций через ExtractValue
Основной способ защиты — никогда не доверять пользовательскому вводу и использовать параметризованные запросы (prepared statements). Это исключает возможность интерпретации ввода как SQL-кода. Дополнительные меры:
- Экранирование специальных символов — если параметризация невозможна, применяйте функции экранирования, предоставляемые драйвером БД.
- Отключение вывода ошибок — настройте веб-сервер и СУБД так, чтобы подробные сообщения об ошибках не попадали в ответ клиенту. Логируйте их, но не показывайте пользователю.
- Принцип наименьших привилегий — учётная запись, от имени которой работает приложение, должна иметь только необходимые права. Например, не давайте доступ к
information_schemaбез надобности. - Регулярное обновление — используйте актуальные версии MySQL и веб-фреймворков, так как в старых версиях могут быть дополнительные уязвимости.
- WAF (Web Application Firewall) — может помочь обнаружить и заблокировать типичные попытки инъекций, но не должен быть единственной линией обороны.
Важно понимать, что EXTRACTVALUE — не уязвимость сама по себе, а инструмент, который становится опасным при наличии ошибок в коде приложения. Разработчикам следует проводить аудит кода и тестирование на проникновение.
Заключение
SQL-инъекция через EXTRACTVALUE — это яркий пример того, как штатные функции СУБД могут быть использованы во вред при недостаточной защите. Понимание механизма таких атак помогает разработчикам и специалистам по безопасности своевременно выявлять и устранять уязвимости. Помните: безопасность — это процесс, а не разовое действие.
Комментарии
—Войдите, чтобы оставить комментарий