Обман веб-кэша: как возникает WCD и как его предотвратить

Обман веб-кэша: как возникает WCD и как его предотвратить

Web Cache Deception WCD — это уязвимость конфигурации кэширующей инфраструктуры, при которой персонализированный ответ приложения ошибочно сохраняется и раздается как общий статический объект. В результате содержимое, зависящее от учетной сессии, становится доступным без аутентификации при обращении по тому же адресу.

Причина возникновения

Кэш на границе сети принимает решение о хранении по ключу кэша и правилам сопоставления. Если политика ориентируется на расширение файла или шаблон пути, а не на заголовки ответа и контекст аутентификации, динамический HTML может быть принят за статический ресурс. Дополнительно риск повышает переписывание путей на уровне прокси или фреймворка, когда разные варианты URL обрабатываются одним и тем же контроллером.

Последовательность эксплуатации

  1. Манипуляция путем. Злоумышленник формирует адрес вида /account/statement.css, хотя контроллер обслуживает /account. Роутер игнорирует суффикс и возвращает персональную страницу.
  2. Неверная классификация ответа. Пограничный кэш применяет политику для статического ресурса по признаку расширения и сохраняет ответ, не учитывая куки или заголовок Authorization.
  3. Повторный доступ без аутентификации. Любой клиент запрашивает тот же адрес и получает ранее сохраненный персональный ответ из кэша.

Предпосылки на стороне инфраструктуры

  • Переписывание пути. Один контроллер обрабатывает /private и /private/произвольный-хвост.jpg.
  • Эвристики по расширению. Правила кэширования привязаны к маскам расширений без верификации контекста аутентификации.
  • Отсутствие санитизации по авторизации. Система кэширования не исключает из хранения ответы, зависящие от Cookie или Authorization.
  • Некорректный ключ кэша. Ключ не учитывает параметры, влияющие на персонализацию, и не привязан к значимым заголовкам.
  • Неверные заголовки ответа. На персональных маршрутах отсутствуют директивы Cache-Control no-store либо private и корректный набор заголовков Vary.

Признаки в телеметрии

  • Непропорционально высокий показатель кэш-попаданий по префиксам, где ответы зависят от сессии пользователя.
  • Рост обращений к адресам с расширениями css js jpg pdf внутри приватных разделов.
  • Несоответствие типа контента ответам из кэша например Content-Type text html для путей с расширением статического ресурса.
  • Снижение нагрузки на origin при увеличении посещений приватных страниц.

Отличие от Web Cache Poisoning

При Web Cache Poisoning кэш хранит подмененный ответ. При Web Cache Deception кэш хранит корректный по содержанию, но персональный ответ, который не должен был попадать в общий слой.

Правильная политика заголовков

  • Cache-Control. Для персональных страниц используйте no-store или private с no-cache. Не полагайтесь на поведение по умолчанию.
  • Vary. Если контент зависит от Cookie Authorization локали или географии, перечислите эти параметры в заголовке Vary. Пример Vary Cookie Authorization Accept-Language.
  • Явный ключ кэша. Формируйте ключ из нормализованного пути и ограниченного набора параметров и заголовков, которые действительно влияют на тело ответа.
  • Negative cache. Короткий TTL для 404 и 403 в приватных разделах уменьшает нагрузку на origin во время перебора вариантов пути.

Распространенные ошибки конфигурации

  • Единые регулярные выражения маршрутизации для приватных и статических путей.
  • Кэширование по маскам расширений внутри приватных префиксов.
  • Отсутствие директив Cache-Control на персональных контроллерах.
  • Ключ кэша не учитывает Cookie или Authorization.
  • Отсутствие нормализации пути и белого списка расширений для кэшируемой статики.

Рекомендации по архитектуре

Нормализация маршрутов и разграничение контуров

  • Статическую отдачу вынести на отдельный префикс или поддомен, обслуживаемый из независимого origin.
  • Приватные контроллеры принимать строго фиксированные пути. Любые попытки добавить расширение в приватный путь должны блокироваться на границе до приложения.
  • Использовать белый список расширений и явные правила кэширования только для статического префикса.

Санитизация кэша по признаку авторизации

  • Если запрос содержит Authorization или сессионный Cookie, кэширования не должно происходить, а ответ приложения должен содержать Cache-Control no-store.
  • На уровне CDN и обратного прокси включить байпас кэша при наличии признаков аутентификации.

Формирование ключа кэша

  • Включать в ключ только нормализованный путь и ограниченный перечень параметров запроса, влияющих на контент, например параметр версии ресурса.
  • Исключать шумовые параметры и нестабильные заголовки.

Negative cache и отказ от эвристик

  • Настроить короткий TTL для кодов 404 и 403 в приватных разделах.
  • Запретить правила вида если расширение jpg то кэшировать внутри приватных префиксов.

Примеры конфигураций в виде псевдокода

Байпас кэша при авторизации

# edge или reverse proxy if request.headers.contains("Authorization") or request.cookies.contains("session") then cache.bypass() response.headers.set("Cache-Control","no-store") end 

Белый список статики

# кэширование только под /static и только разрешенные расширения if path.starts_with("/static/") and ext in [".css",".js",".png",".jpg",".svg",".woff2"] then cache.allow(ttl="24h", key=normalize(path, query=["v"])) else cache.bypass() end 

Защита приватных маршрутов от добавления расширений

# блокировка попыток обращения к приватным страницам с суффиксом расширения if path.starts_with("/account/") and path.matches(".(css|js|png|jpg|svg|pdf)$") then return 404 end 

Заголовки ответа для персонального HTML

HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 Cache-Control: no-store Vary: Cookie, Authorization, Accept-Language 

Наблюдаемость и контроль

  • Логи кэша с полями ключ кэширования признак попадания причина решения и информация об авторизации.
  • Алерт при резком росте кэш-попаданий по приватным префиксам.
  • Алерт при несоответствии Content-Type и предполагаемого типа по расширению пути.
  • Трассировка с меткой источник ответа кэш или origin для приватных префиксов.

Порядок реагирования

Первые минуты

  • Включить байпас кэша для приватных префиксов account user admin.
  • Отключить правила кэширования по расширениям внутри приватных префиксов.
  • Снизить TTL публичного кэша до безопасного значения и включить revalidate.

Первый час

  • Извлечь статистику кэш-попаданий по приватным путям и сопоставить с наличием признаков авторизации.
  • Включить negative cache для 404 и 403 и нормализацию пути.
  • Выпустить обновления контроллеров с Cache-Control no-store и корректным набором Vary.

Первые сутки

  • Разнести статику и динамику на разные домены или зоны кэширования.
  • Добавить юнит- и интеграционные тесты, имитирующие обращение к приватным разделам с масками расширений, и проверку поведения кэша для анонимного клиента.
  • Задокументировать матрицу кэш-политик для каждого префикса.

Автоматические проверки

В конвейер сборки имеет смысл добавить тест с двумя клиентами. Первый клиент выполняет аутентификацию и получает ответ по адресу вида /account/detail.jpg с фиксацией заголовков и источника ответа. Второй клиент без аутентификации обращается по тому же адресу. Тест считается неуспешным, если второй клиент получает содержимое, отличное от 404 403 или перенаправления на страницу входа.


CDN reverse proxy WCD Web Cache Deception веб кэш обман кэша
Alt text
Обращаем внимание, что все материалы в этом блоге представляют личное мнение их авторов. Редакция SecurityLab.ru не несет ответственности за точность, полноту и достоверность опубликованных данных. Вся информация предоставлена «как есть» и может не соответствовать официальной позиции компании.
Хакеры ненавидят этот канал!

Спойлер: мы раскрываем их любимые трюки

Расстройте их планы — подпишитесь

Техно Леди

Технологии и наука для гуманитариев