Интересная и практичная Cookie Bomb
Last updated
Last updated
В предыдущем посте мы узнали о 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
, необходимо иметь возможность записывать куки. Существует два основных способа достижения этого. Первый способ — это эксплуатация логики самого веб-сайта.
Например, предположим, что есть страница 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 есть два, связанных с тем, что запрос слишком велик:
413 Payload Too Large
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
, который позволяет нам устанавливать произвольные куки. Следующие шаги таковы:
Найти способ записать куки размером более 8KB
(так как многие ограничения серверов находятся около 8KB
).
Передать этот URL цели атаки и найти способ заставить ее кликнуть по нему.
Цель кликает по URL и устанавливает очень большие куки в своем браузере.
Цель посещает веб-сайт https://example.com
и обнаруживает, что не может увидеть никакого контента, только пустую страницу или сообщение об ошибке.
Атака успешна.
В этой ситуации, если пользователь не изменит свой браузер или куки не истекут, или не очистит куки вручную, он всегда будет находиться в этом состоянии.
Подводя итог, эта атака может нацеливаться только на конкретных пользователей и требует двух предварительных условий:
Найти место, где можно установить произвольные куки.
Цель должна кликнуть по URL, найденному на первом шаге.
Он нашел следующий код на сайте Twitter:
Можно увидеть, что данные из 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
.
Например, следующие домены находятся в этом списке:
com.tw
gov.tw
github.io
Таким образом, ранее упомянутый пример недействителен, потому что когда я нахожусь на userA.github.io
, я не могу установить куки для github.io
, поэтому атака Cookie Bomb
не может быть выполнена.
Существует два предварительных условия для успешности вышеупомянутых атак:
Найти место, где можно установить произвольные куки.
Цель должна кликнуть по URL, найденному на первом шаге.
Чтобы сделать атаку более успешной, мы можем рассмотреть следующее в отношении этих двух предварительных условий:
Возможно ли легко найти это место?
Возможно ли, чтобы цель была скомпрометирована без клика по ссылке?
Второй пункт можно реализовать через уязвимость, называемую Cache Poisoning
.
Как следует из названия, эта уязвимость связана с загрязнением содержимого в кэше. Например, многие веб-сайты имеют кэши, и разные пользователи могут получать доступ к одному и тому же кэшу. В этом случае я могу найти способ заставить сервер кэша сохранить поврежденный ответ. Таким образом, все другие пользователи также получат поврежденный файл и увидят одно и то же сообщение об ошибке.
Таким образом, цель может быть скомпрометирована без клика по каким-либо ссылкам, и атака расширяется с одного человека на всех.
Теперь давайте рассмотрим первый пункт: "Возможно ли легко найти это место?".
Есть ли место, где мы можем легко установить куки для выполнения Cookie Bomb
?
Да, это общие поддомены, упомянутые ранее, такие как *.github.io
.
Но разве эти домены уже не находятся в списке public suffix
?
Они не могут устанавливать куки.
Просто найдите тот, который не находится в списке!
Однако это не простая задача, потому что вы обнаружите, что большинство известных вам сервисов уже зарегистрированы. Например, GitHub, AmazonS3, Heroku и Netlify уже находятся в списке.
Но я нашел один, который не находится в списке, и это Azure CDN, предоставляемый Microsoft: azureedge.net.
Не знаю почему, но этот домен не принадлежит к public suffix
, так что если я создам свой собственный CDN, я смогу выполнить Cookie Bomb
.
Далее, загрузите файл на Azure и настройте CDN.
После клика по нему будет установлено множество мусорных куки на azureedge.net:
После обновления вы обнаружите, что веб-сайт больше недоступен:
Это означает, что Cookie Bomb
была успешной.
Таким образом, все ресурсы, размещенные на azureedge.net
, будут затронуты.
На самом деле, Azure CDN имеет возможность использовать пользовательские домены, так что если вы используете пользовательский домен, вы не будете затронуты. Однако некоторые веб-сайты не используют пользовательские домены и напрямую используют azureedge.net в качестве URL.
Лучшей мерой смягчения является использование пользовательского домена вместо стандартного azureedge.net. Таким образом, вы избежите проблемы с Cookie Bomb
. Но помимо пользовательских доменов, azureedge.net должен быть зарегистрирован как public suffix
, чтобы действительно решить проблему.
Помимо этих двух мер защиты, есть еще одна, о которой вы, возможно, не подумали.
Как фронтенд-инженеры, мы обычно включаем ресурсы таким образом:
Просто добавьте атрибут crossorigin
:
Вы можете избежать атак 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
сами по себе могут не иметь большого влияния, при комбинировании с другими элементами они могут потенциально привести к серьезным уязвимостям. Например, мы ранее видели, как сайты с одинаковым происхождением могут обойти ограничения куки с одинаковым происхождением и эксплуатировать ограничения CORS
через проблемы парсинга в заголовке content-type
, что приводит к уязвимости CSRF
.
Он обнаружил уязвимость XSS
на example.co
m, который использовал Google OAuth для входа. Он подумал, что может использовать XSS
для кражи OAuth-кода и получить прямой доступ к учетной записи пользователя, превратив это в более серьезную уязвимость захвата учетной записи.
Типичный поток OAuth выглядит следующим образом:
Пользователь нажимает кнопку "Войти с Google".
Веб-страница перенаправляет на https://google.com/oauth?client_id=example
.
Пользователь входит в систему и предоставляет разрешение на Google.
Веб-страница перенаправляет на https://example.com/oauth/callback?code=123
.
Веб-страница далее перенаправляет на 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
, чтобы добавлять его единообразно:
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
. Поэтому запросы могут быть отправлены с этой страницы, как показано в следующем примере:
Методы подобного рода обходят ограничения 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 Bom
b. Вы даже можете запустить атаку прямо со своего компьютера, не используя куки.
Код, который я использовал для демонстрации, выглядит следующим образом, он был взят за основу и модифицирован :
Первый случай, который я хочу представить, появился в докладе filedescriptor на HITCON CMT в 2019 году: .
На первый взгляд, проблем не видно. Однако, если nginx
возвращает ошибку 4xx или 5xx, этот заголовок не будет добавлен к ответу. Это стандартное поведение nginx, как указано в :
Эта статья адаптирована из: