Обман веб-кэша — когда конф. данные становятся статикой
Всем привет. На выходных решил немного вернуться к тому, с чего начинался мой путь в ИБ. Кроме книг, это были лаборатории PortSwigger.
В тот период я довольно плотно практиковался и закрыл больше 50% лаб, прежде чем пошёл по тех. интервью и в итоге попал в AppSec в окко.
И вот недавно я добил направление, которое ещё с прошлого года висело у меня не закрытым, — уязвимости, связанные с веб-кэшем.
Решил сделать 2 поста: • Web Cache Deception — обман веб-кэша • Web Cache Poisoning — отравление веб-кэша
Сегодня первая часть — про обман веб-кэша. На скрине к посту как раз оставлю решённую expert-лабу по этой теме.
━━━━━━━━━━ Что такое веб-кэш ━━━━━━━━━━
Если совсем просто, кэш нужен для того, чтобы не гонять один и тот же статический контент с сервера каждый раз.
Например: • .css • .js • изображения • favicon.ico • файлы из /static, /assets, /images
Такие ресурсы часто отдаются через CDN или промежуточный cache server. Это снижает нагрузку на backend и ускоряет доставку контента пользователю. Но проблема начинается там, где кэш и основной сервер по-разному понимают один и тот же URL.
━━━━━━━━━━ Что такое Web Cache Deception ━━━━━━━━━━
Web Cache Deception — это уязвимость, при которой атакующий заставляет кэш сохранить приватный динамический ответ как будто это обычный статический файл.
То есть сервер может думать: ➤ “это /profile, надо отдать данные пользователя”
А кэш может думать: ➤ “это /profile?wcd.css, похоже на статику, надо сохранить”
В итоге жертва переходит по специально подготовленной ссылке, её приватный ответ попадает в кэш, а атакующий потом запрашивает этот же URL и получает уже закэшированную конфиденциальную информацию.
Главная суть здесь не в “магии кэша”, а в расхождении между тем: • как URL интерпретирует origin server • и как этот же URL интерпретирует cache/CDN
━━━━━━━━━━ Основные направления эксплуатации ━━━━━━━━━━
PortSwigger выделяет несколько больших подходов, и я бы кратко описал их так:
➤ Правила статических расширений Когда кэш сохраняет всё, что заканчивается на .css, .js, .ico и т.д.
➤ Правила статических директорий Когда кэш доверяет путям вроде /static, /assets, /scripts, /images.
➤ Правила конкретных имён файлов Когда кэш ориентируется на robots.txt, index.html, favicon.ico и похожие файлы.
И во всех этих случаях ключевая мысль одна: нужно найти URL, который backend воспримет как динамический endpoint, а кэш — как статический ресурс.
━━━━━━━━━━ Как это искать ━━━━━━━━━━
Мой короткий флоу после лаб выглядит так: • найти endpoint с чувствительными данными • посмотреть, кэшируются ли статические ресурсы • искать расхождения в обработке URL • тестировать расширения, разделители и нормализацию пути • проверять заголовки вроде X-Cache, Age, Cache-Control • сравнивать первый и повторный запрос
Пример логики я приводил выше с /profile?wcd.css
━━━━━━━━━━ Как защищаться ━━━━━━━━━━
Базовые меры защиты выглядят так: • динамические ответы помечать Cache-Control: no-store или private • не давать CDN переопределять Cache-Control для приватных данных • проверять, что Content-Type ответа соответствует расширению в URL • включать защиту CDN от cache deception, если она есть • не кэшировать ответы, зависящие от cookies, сессии или авторизации • проверять, что origin server и cache server одинаково интерпретируют URL • аккуратно настраивать правила для /static, /assets и файловых расширений
━━━━━━━━━━ Мини-итог ━━━━━━━━━━
Web Cache Deception я раскрыл не полностью и более подробно можно ознакомиться по ссылке ниже, напрямую от PortSwigger ➥ https://portswigger.net/web-security/web-cache-deception
Во второй части я разберу уже Web Cache Poisoning там кэш используется не для вытаскивания приватного ответа, а для подмены того что потом увидят другие пользователи.
#AppSec #PortSwigger #BugBounty #Pentest #WebSecurity #CyberSecurity