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
  • CORS Misconfiguration
  • Пример из реальной жизни
  • Other COXX Series Headers
  • Serious Security Vulnerabilities: Meltdown and Spectre
  • Super Simplified Explanation of Spectre Attack
  • CORB (Cross-Origin Read Blocking)
  • CORP (Cross-Origin Resource Policy)
  • Site Isolation
  • COEP (Cross-Origin-Embedder-Policy)
  • COOP (Cross-Origin-Opener-Policy)
  • Returning to the cross-origin isolated state
  • Заключение
  1. Глава 4 - Межсайтовые атаки

Проблемы Cross-Origin безопасности

Хотя некоторые веб-сайты используют reverse proxy или другие механизмы, чтобы разместить фронтенд и бэкенд под одним Origin, это, похоже, является исключением, а не нормой. В большинстве случаев разрешение доступа фронтенда к Cross-Origin API бэкенда почти неизбежно.

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

Помимо неправильной настройки параметров CORS, существуют также проблемы безопасности с Cross-Origin доступом для таких элементов, как <img> или <script>.

CORS Misconfiguration

Как упоминалось ранее, если Cross-Origin непростой запрос хочет включить куки, Access-Control-Allow-Origin не может быть *. Он должен указывать один источник; в противном случае браузер не разрешит это.

Но на практике у нас не может быть только одного источника. У нас может быть несколько источников, таких как buy.example.com, social.example.org, note.example.com.tw, всем из которых нужен доступ к api.example.com. В этом случае мы не можем жестко закодировать источник в заголовке ответа и его нужно динамически настраивать.

Давайте начнем с худшего подхода, который заключается в том, что:

app.use((req, res, next) => {
  res.headers['Access-Control-Allow-Credentials'] = 'true';
  res.headers['Access-Control-Allow-Origin'] = req.headers['Origin'];
  next();
});

Происхождение (Origin) берется напрямую из заголовка запроса для удобства. Делая это, любое происхождение может пройти проверку CORS.

Какие проблемы у этого подхода?

Предположим, я создаю веб-сайт с URL https://fake-example.com и пытаюсь заставить пользователей кликнуть на него. Внутри сайта есть скрипт:

fetch('https://api.example.com/me', {  
  credentials: 'include'  
})  
.then(res => res.text())  
.then(res => {  
  console.log(res)   
  window.location = 'https://example.com'  
})

Поскольку сервер возвращает правильный заголовок, признавая https://fake-example.com как допустимый Origin, проверка CORS проходит. Поэтому этот веб-сайт также может получать данные с http://api.example.com/me.

В результате эта атака затронет только пользователей, которые посещают веб-сайт и вошли в систему на example.com. Влияние зависит от API веб-сайта. Минимум, к которому можно получить доступ, — это данные пользователя, а в более серьезных случаях может быть получен токен пользователя (если такой API существует).

Есть несколько моментов, которые следует отметить об этой атаке:

  1. Это не XSS, потому что я не выполняю код на example.com. Я выполняю его на своем собственном веб-сайте, http://fake-example.com.

  2. Это отчасти похоже на CSRF, но веб-сайты обычно не добавляют защиту CSRF-токенами к GET API, поэтому это может пройти.

  3. Если установлены куки SameSite, атака потерпит неудачу, потому что куки не будут отправлены.

(О CSRF и SameSite будет сказано позже)

Таким образом, для успешной атаки необходимо выполнить несколько предварительных условий:

  1. Заголовки CORS предоставляются несанкционированному происхождению.

  2. Веб-сайт использует куки для аутентификации и не устанавливает SameSite.

  3. Пользователь активно кликает на веб-сайт и вошел в систему.

Что касается первого пункта, маловероятно, что кто-то напишет код, подобный приведенному выше, напрямую используя Origin из заголовка запроса. Более вероятный подход:

app.use((req, res, next) => {  
  res.headers['Access-Control-Allow-Credentials'] = 'true'  
  const origin = req.headers['Origin']  
  if (/example\.com$/.test(origin)) {  
    res.headers['Access-Control-Allow-Origin'] = origin  
  }  
})

Таким образом, следующие Origin могут пройти:

  1. example.com

  2. buy.example.com

  3. social.example.com

Однако у этого подхода есть проблема, потому что также может пройти:

  1. fakeexample.com

Уязвимости, подобные этой, вызваны неправильными настройками CORS и поэтому называются неправильной настройкой CORS.

Решение заключается в том, чтобы не использовать RegExp для проверки, а заранее подготовить список разрешенных источников (allow-list). Только Origin, которые появляются в списке, могут пройти; в противном случае они будут отклонены. Таким образом, мы можем гарантировать, что в процессе проверки нет уязвимостей, и не забываем добавлять атрибут SameSite к кукам.

const allowOrigins = [  
  'https://example.com',  
  'https://buy.example.com',  
  'https://social.example.com'  
];

app.use((req, res, next) => {  
  res.headers['Access-Control-Allow-Credentials'] = 'true';  
  const origin = req.headers['Origin'];  
  if (allowOrigins.includes(origin)) {  
    res.headers['Access-Control-Allow-Origin'] = origin;  
  }  
});

Пример из реальной жизни

Первый пример — это уязвимость, обнаруженная Джорданом Милном в JetBrains IDE в 2016 году.

При использовании JetBrains IDE запускается локальный сервер. Когда вы открываете файл и нажимаете "просмотреть в браузере", он открывает URL: http://localhost:63342/<projectname>/<your_file.html>, который обрабатывается локальным сервером за кулисами.

И этот сервер реализован не очень хорошо. Его заголовок Access-Control-Allow-Origin такой же, как в примере неправильной конфигурации, который я упоминал ранее, он напрямую использует заголовок Origin из запроса. Поэтому любой веб-сайт может читать ответ.

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

Простой PoC, предоставленный автором, выглядит следующим образом:

<script>
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://localhost:63342/testing/something.txt", true);
xhr.onload = function() { alert(xhr.responseText) };
xhr.send();
</script>

Второй случай касается уязвимости в бирже Bitcoin, о которой сообщил Джеймс Кеттл на конференции AppSec EU 2017 года.

Он обнаружил, что один из API биржи имел ту же уязвимость, позволяя любому Origin читать ответ. Один из API был /api/requestApiKey, который мог получить apiKey пользователя. Этот apiKey мог быть использован для перевода биткойнов пользователя на другой аккаунт.

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

Other COXX Series Headers

Помимо знакомого CORS, существует несколько заголовков, начинающихся с CO:

  1. CORB (Cross-Origin Read Blocking)

  2. CORP (Cross-Origin Resource Policy)

  3. COEP (Cross-Origin-Embedder-Policy)

  4. COOP (Cross-Origin-Opener-Policy)

Эти заголовки с CO также связаны с доступом к данным из разных Origins. Теперь давайте посмотрим, что делают эти заголовки.

Serious Security Vulnerabilities: Meltdown and Spectre

  • Variant 1: bounds check bypass (CVE-2017-5753)

  • Variant 2: branch target injection (CVE-2017-5715)

  • Variant 3: rogue data cache load (CVE-2017-5754)

Первые два варианта известны как Spectre, а третий — как Meltdown. Если вы помните, это была большая проблема в то время, потому что проблема заключалась в CPU и ее было не так просто исправить.

Я думаю, что раскрытие этой уязвимости оказало значительное влияние на механизм работы браузеров (или, по крайней мере, ускорило эволюцию браузеров). Особенно Spectre может быть использован для атак на браузеры, что также затрагивает тему этой серии: Cross-Origin Resource Sharing.

Поэтому необходимо иметь базовое представление о том, что делает Spectre. Чтобы полностью понять эту атаку, требуется много дополнительных знаний. Поэтому ниже я объясню Spectre, используя сильно упрощенную версию. Если вы хотите полностью понять это, вы можете обратиться к ссылке выше.

Super Simplified Explanation of Spectre Attack

Снова важно отметить, что это упрощенная версия для более простого понимания. Она может отличаться от оригинальной атаки, но основная концепция должна быть схожей.

Предположим, у нас есть кусок кода (на языке C), который выглядит так:

uint8_t arr1[16] = {1, 2, 3}; 
uint8_t arr2[256]; 
unsigned int array1_size = 16;

void run(size_t x) {  
  if(x < array1_size) {    
    uint8_t y = array2[array1[x]];  
  }  
}

size_t x = 1; 
run(x);

Я объявил два массива типа uint8_t, так что каждый элемент в массивах будет размером 1 байт (8 бит). Длина arr1 составляет 16, а длина arr2 — 256.

Далее у меня есть функция под названием run, которая принимает число x в качестве входного параметра. Она проверяет, меньше ли x, чем array1_size. Если да, то она получает значение array1[x], использует его как индекс для доступа к array2 и присваивает полученное значение переменной y.

В приведенном выше примере, если мы вызовем run(1), он выполнит:

uint8_t y = array2[array1[1]];

Поскольку значение array1[1] равно 2, это становится y = array2[2].

Этот код кажется нормальным, и я также добавил проверку длины массива, так что не будет доступа за пределами границ (OOB), если только x не меньше array1_size.

Однако это только то, как это выглядит для вас.

Когда CPU выполняет код, существует механизм, называемый предсказанием ветвлений. Чтобы улучшить эффективность выполнения кода, CPU предсказывает, будет ли условие if истинным или ложным. Если предсказание истинно, он выполняет код внутри оператора if и заранее вычисляет результат.

Все это — просто "предсказание". После фактического выполнения условия if, если результат совпадает с предсказанием, все в порядке. Но если он не совпадает, ранее вычисленный результат отбрасывается. Этот механизм называется спекулятивным выполнением.

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

И это основная причина, почему атака Spectre работает, потому что действительно остаются некоторые подсказки.

Чтобы дополнительно улучшить эффективность выполнения, во время спекулятивного выполнения некоторые результаты хранятся в кэше CPU для повышения эффективности извлечения данных.

Предположим, у нас есть три вещи: A, B и C. Одна из них находится в кэше CPU, а две другие — нет. Как мы можем определить, какая из них в кэше?

Ответ заключается в наблюдении за временем доступа к этим трем вещам! Поскольку доступ к чему-то в кэше CPU быстрее, если доступ к A занимает 10 мс, к B — 10 мс, а к C — всего 1 мс, мы можем заключить, что C находится в кэше CPU. Этот тип атаки, который получает информацию через другие каналы, называется атакой через побочный канал.

В приведенном выше методе мы определяем на основе времени, поэтому это также известно как временная атака.

Теперь давайте вернемся к предыдущему коду:

uint8_t arr1[16] = {1, 2, 3}; 
uint8_t arr2[256]; 
unsigned int array1_size = 16;

void run(size_t x) {  
  if(x < array1_size) {    
    uint8_t y = array2[array1[x]];  
  }  
}

size_t x = 1; 
run(x);

Предположим, что мы многократно запускаем run(10). На основе предсказания ветвлений CPU разумно предсказывает, что следующее выполнение также удовлетворит условию if и выполняет код внутри. В этот момент я внезапно устанавливаю x в 100 и запускаю run(100).

Код внутри оператора if будет спекулятивно выполнен:

uint8_t y = array2[array1[100]];

Предположим, значение array1[100] равно 38. Таким образом, это становится y = array2[38], и array2[38] хранится в кэше CPU, повышая эффективность последующего извлечения данных.

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

Теперь, основываясь на временной атаке, о которой мы говорили ранее, мы читаем каждый элемент array2 и измеряем время. Мы обнаружим, что время доступа к array2[38] является самым коротким.

В этот момент мы знаем одну вещь:

Содержимое array1[100] равно 38.

Вы можете спросить: "И что вы можете сделать с этой информацией?" Существует множество вещей, которые можно сделать. Поскольку длина array1 составляет всего 16, значение, которое мы читаем, не из самого array1, а из других частей памяти, к которым мы не должны были иметь доступ. Постоянно воспроизводя этот шаблон, мы можем читать данные из других мест.

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

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

Проще говоря, "Spectre позволяет вам потенциально читать данные с других веб-сайтов, используя браузер."

Объяснение Spectre на этом заканчивается. Подробности были упрощены выше, и я тоже не полностью понимаю эти детали. Если вы хотите узнать больше, вы можете обратиться к:

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

С этой точки зрения давайте рассмотрим различные связанные механизмы.

CORB (Cross-Origin Read Blocking)

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

Веб-сайт имеет множество способов для загрузки Cross-Origin ресурсов, таких как fetch или xhr, но эти два метода уже контролируются CORS, и полученный ответ должен храниться в сетевом процессе, а не в собственном процессе веб-сайта. Поэтому даже с Spectre его нельзя прочитать.

Однако использование тегов <img> или <script> может легко загрузить ресурсы с других веб-сайтов. Например: <img src="https://bank.com/secret.json">. Предположим, что secret.json — это конфиденциальные данные, мы можем "загрузить" эти конфиденциальные данные.

Вы можете задаться вопросом: "Какой в этом смысл? Это не изображение, и я не могу получить к нему доступ с помощью JavaScript." Верно, это не изображение, но с точки зрения механизма работы Chrome, Chrome не знает, что это не изображение, до его загрузки (это может иметь расширение файла .json, но на самом деле быть изображением), поэтому он сначала загружает его. После загрузки он отправляет результат в процесс рендеринга, и только тогда понимает, что это не изображение, что вызывает ошибку загрузки.

Может показаться, что проблем нет, но не забывайте, что Spectre открыл новое окно, где "любые данные в одном процессе могут быть потенциально прочитаны". Поэтому просто "отправка результата в процесс рендеринга" недостаточна, потому что через атаки Spectre злоумышленники все равно могут получить доступ к данным, хранящимся в памяти.

Таким образом, цель механизма CORB заключается в следующем:

If the data type you want to read is completely unreasonable, there is no need to read it into the render process, just discard the result!

Продолжая с приведенным выше примером, если MIME-тип этого JSON-файла — application/json, это означает, что он не может быть изображением, поэтому его нельзя поместить внутрь тега img. Вот что я имею в виду под "неразумным типом данных для чтения".

CORB в основном защищает три типа данных: HTML, XML и JSON. Как браузер знает, является ли это одним из этих трех типов? Давайте определим это по типу содержимого в заголовке ответа, верно?

К сожалению, это невозможно. Причина в том, что многие веб-сайты неправильно устанавливают типы содержимого. Возможно, что файл JavaScript установлен как text/html, и тогда CORB блокирует его, что приводит к сбою.

Поэтому Chrome будет определять (sniffing) тип файла на основе его содержимого, чтобы решить, применять ли CORB или нет.

Однако также существует вероятность ошибочного суждения. Поэтому, если тип содержимого, предоставляемый вашим сервером, всегда правильный, вы можете отправить заголовок ответа X-Content-Type-Options: nosniff, и Chrome будет напрямую использовать указанный вами тип содержимого вместо его определения.

В заключение, CORB — это механизм, который уже встроен в Chrome. Он автоматически блокирует загрузку неразумных Cross-Origin ресурсов, таких как использование <img> для загрузки JSON или использование <script> для загрузки HTML и так далее.

Более подробные объяснения вы можете найти в разделе:

CORP (Cross-Origin Resource Policy)

CORB — это встроенный механизм в браузерах, который автоматически защищает HTML, XML и JSON от загрузки в кросс-доменные процессы рендеринга, тем самым предотвращая атаки Spectre. Но что насчет других ресурсов? Если есть другие типы ресурсов, такие как определенные фотографии и видео, которые также являются конфиденциальными данными, могу ли я защитить их?

Cross-Origin Read Blocking (CORB) automatically protects against Spectre attacks that load cross-origin, cross-type HTML, XML, and JSON resources, and is based on the browser’s ability to distinguish resource types. We think CORB is a good idea. From-Origin would offer servers an opt-in protection beyond CORB.

Если вы знаете, какие ресурсы необходимо защитить, вы можете использовать заголовок CORP, чтобы указать, какие Origin могут загружать эти ресурсы. У CORP есть три опции:

  1. Same-Site

  2. Same-Origin

  3. Cross-Origin

Третья опция аналогична отсутствию установки (но есть небольшая разница, которая будет объяснена позже), что означает, что все Cross-Origin источники могут загружать ресурс. Давайте посмотрим, что произойдет после установки этого заголовка!

Сначала запустим простой сервер с использованием express, добавим заголовок CORP и разместим изображение с URL http://b.example.com/logo.jpg:

app.use((req, res, next) => {  
  res.header('Cross-Origin-Resource-Policy', 'same-origin')  
  next()
})
app.use(express.static('public'));

Затем, на http://a.example.com, давайте включим это изображение:

<img src="http://b.example.com/logo.jpg" />

Когда вы обновите страницу и откроете консоль, вы увидите сообщение об ошибке, указывающее на то, что изображение не удалось загрузить. Открытие вкладки сети предоставит подробное объяснение причины:

Если вы измените заголовок на Same-Site или Cross-Origin, вы сможете увидеть, что изображение загружается корректно.

Таким образом, этот заголовок фактически является "CORS на уровне ресурсов". Оригинальный CORS больше похож на протокол для доступа к API или "данным" между разными источниками, позволяя Cross-Origin доступ к данным с разрешением. Однако, когда речь идет о загрузке ресурсов, таких как использование <img> или <script>, если вы хотите предотвратить Cross-Origin загрузку, вам нужно полагаться только на серверную логику для определения значений Origin или Referer и динамически решать, возвращать ли данные.

С введением заголовка CORP он предоставляет метод для блокировки "любой Cross-Origin загрузки" просто путем установки заголовка. Таким образом, это не только вопрос безопасности; безопасность — это лишь один аспект. Ключевым моментом является то, что вы можете предотвратить загрузку ваших ресурсов другими.

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

Inline linking — the practice of embedding resources (e.g. images or fonts) from another server, causing the owner of that server to get a higher hosting bill.

Clickjacking — embedding a resource from another origin and attempting to let the visitor click on a concealed link thereof, causing harm to the visitor.

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

Privacy leakage — sometimes resource availability depends on whether a visitor is signed in to a particular website. E.g. only with a I'm-signed-in-cookie will an image be returned, and if there is no such cookie an HTML document. An HTML document embedding such a resource (requested with the user's credentials) can figure out the existence of that resource and thus whether the visitor is signed in and therefore has an account with a particular service.

Существуют также проблемы конфиденциальности. Например, веб-сайт может определить, вошли ли вы в систему на других веб-сайтах (что будет обсуждено позже).

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

<img src=xxx onerror="alert('not login')" onload="alert('login')">

Проверяя, загружается ли изображение успешно, я могу определить, вошли ли вы в систему.

License checking — certain font licenses require that the font be prevented from being embedded on other origins.

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

В заключение, ранее введенный CORB только "предотвращает неразумное чтение", такое как загрузка HTML с использованием img, что является чисто вопросом безопасности

Однако CORP может предотвратить любое чтение (за исключением iframes, на которые он не влияет) и может защитить ресурсы вашего веб-сайта от загрузки другими. Это более мощный и широко применимый заголовок.

В настоящее время основные браузеры уже поддерживают этот заголовок.

Site Isolation

Чтобы предотвратить атаки Spectre, существуют два подхода:

  1. Предотвратить возможность злоумышленников выполнять атаки Spectre.

  2. Даже если атака будет выполнена, предотвратить получение желаемой информации.

Принцип атак Spectre был упомянут ранее и заключается в определении того, какие данные хранятся в кэше, измеряя время, необходимое для чтения данных. Таким образом, злоумышленники могут "украсть" данные из памяти. Если время, предоставляемое функцией таймера браузера, намеренно сделать неточным, разве это не защитит от атаки? Поскольку рассчитанное время злоумышленника будет схожим, они не смогут определить, какой результат чтения быстрее.

После появления атак Spectre браузеры предприняли два действия:

  1. Уменьшили точность функции performance.now.

  2. Отключили SharedArrayBuffer.

Первый пункт легко понять: уменьшая точность функции времени, злоумышленники не могут определить правильную скорость чтения. Но почему второй пункт?

Давайте поговорим о SharedArrayBuffer. Он позволяет JavaScript в вашем документе делиться одним и тем же блоком памяти с веб-воркерами, что позволяет обмениваться данными. Таким образом, в веб-воркере вы можете создать счетчик, который будет постоянно увеличиваться, а затем прочитать этот счетчик в JavaScript, достигая функции таймера.

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

Другой подход заключается в том, чтобы предотвратить доступ вредоносных веб-сайтов к информации с Cross-Origin веб-сайтов, что ранее упоминалось как CORB, и теперь вводится: Site Isolation.

Site Isolation is a security feature in Chrome that offers an additional line of defense to make such attacks less likely to succeed. It ensures that pages from different websites are always put into different processes, each running in a sandbox that limits what the process is allowed to do. It also blocks the process from receiving certain types of sensitive data from other sites.

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

Site Isolation в настоящее время включен по умолчанию в Chrome. Соответствующий недостаток заключается в том, что он потребляет больше памяти, так как создается больше процессов. Для других последствий вы можете обратиться к вышеупомянутой статье.

Помимо Site Isolation, существует еще одно понятие, которое легко спутать, называемое "Cross-Origin Isolated State."

Определение "Site" в Site Isolation такое же, как концепция Same-Site. Например, http://a.example.com и http://b.example.com считаются Same-Site. Поэтому даже при Site Isolation эти две веб-страницы все равно будут помещены в один и тот же процесс.

А Cross-Origin Isolated State должно быть более строгой изоляцией, изолируя все, что не является одним и тем же источником, даже если они Same-Site. Поэтому http://a.example.com и http://b.example.com будут изолированы. Более того, Site Isolation изолирует процессы, в то время как Cross-Origin Isolated State, похоже, изолирует группы контекстов просмотра, предотвращая нахождение Cross-Origin ресурсов в одной и той же группе контекстов просмотра.

Это Cross-Origin изолированное состояние не включено по умолчанию и требует установки этих двух заголовков на веб-странице:

  1. Cross-Origin-Embedder-Policy: require-corp

  2. Cross-Origin-Opener-Policy: same-origin

Что касается того, почему именно эти два заголовка, я объясню позже.

COEP (Cross-Origin-Embedder-Policy)

Чтобы достичь Cross-Origin Isolated State, необходимо убедиться, что все Cross-Origin обращения на вашем веб-сайте являются законными и авторизованными.

Заголовок COEP (Cross-Origin-Embedder-Policy) имеет два значения:

  1. unsafe-none

  2. require-corp

Первое значение является значением по умолчанию, что означает отсутствие ограничений. Второе значение связано с CORP (Cross-Origin-Resource-Policy), упомянутым ранее. Если вы используете require-corp, это означает, что вы говорите браузеру: "Все ресурсы, которые я загружаю на странице, должны иметь заголовок CORP (или CORS) и быть законными."

Теперь предположим, что у нас есть веб-сайт a.example.com, и мы хотим сделать его Cross-Origin Isolated State. Поэтому мы добавляем заголовок: Cross-Origin-Embedder-Policy: require-corp. Затем мы импортируем ресурс на веб-странице:

<img src="http://b.example.com/logo.jpg">

Далее мы отправляем правильный заголовок на стороне b:

app.use((req, res, next) => {  
  res.header('Cross-Origin-Resource-Policy', 'cross-origin')  
  next()
})

Таким образом, первый шаг достигнут.

Также я упоминал ранее, что существует небольшая разница между отсутствием установки CORP и установкой его как Cross-Origin, и она заключается как раз в этом. В приведенном выше примере, если сторона b не отправляет этот заголовок, политика встраивания не пройдет.

COOP (Cross-Origin-Opener-Policy)

Второй шаг — это заголовок COOP (Cross-Origin-Opener-Policy). Когда вы используете window.open для открытия веб-страницы, вы можете управлять location этой веб-страницы, и открытая веб-страница также может управлять вашей веб-страницей с помощью window.opener.

Наличие такой связи между окнами не соответствует Cross-Origin Isolated Поэтому заголовок COOP используется для регулирования отношений между окнами и открывателями. У него есть три значения:

  1. Cross-Origin-Opener-Policy: unsafe-none

  2. Cross-Origin-Opener-Policy: same-origin

  3. Cross-Origin-Opener-Policy: same-origin-allow-popups

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

Предположим, есть веб-страница A, которая открывает веб-страницу B с помощью window.open:

  1. Если AB является Cross-Origin, браузер уже имеет ограничения и может получить доступ только к методам, таким как window.location или window.close. Он не может получить доступ к DOM или чему-либо еще.

  2. Если AB является Same-Origin, они могут почти полностью получать доступ друг к другу, включая DOM.

  3. Если A добавляет заголовок COOP со значением Same-Origin, это означает наложение дополнительных ограничений для второй части. Оба A и B должны иметь этот заголовок со значением Same-Origin, чтобы получить доступ к окнам друг друга.

  4. Если A добавляет заголовок COOP со значением Same-Origin-Allow-Popups, это также ограничивает второй случай, но более лояльно. Пока заголовок COOP у B не равен Same-Origin, они могут получать доступ к окнам друг друга.

В заключение, чтобы иметь "возможность доступа к окнам друг друга", они сначала должны быть Same-Origin, и это неизменяемо. Могут ли они получить доступ друг к другу, зависит от того, установлен ли заголовок COOP и от значения этого заголовка.

Если заголовок COOP установлен, но не соответствует правилам, window.opener станет null, и даже location не может быть получено (если правила не установлены, оно может быть получено, даже если это Cross-Origin).

Returning to the cross-origin isolated state

Как упоминалось ранее, Cross-Origin Isolated State требует установки этих двух заголовков:

  1. Cross-Origin-Embedder-Policy: require-corp

  2. Cross-Origin-Opener-Policy: same-origin

Почему? Потому что, как только они установлены, это означает, что у вас есть разрешение на доступ ко всем Cross-Origin ресурсам на странице. Если у вас нет разрешения, произойдет ошибка. Таким образом, если заголовки установлены и проходят проверку, это означает, что вам разрешен доступ ко всем Cross-Origin ресурсам, и не будет проблем с безопасностью.

На веб-сайте вы можете использовать:

self.crossOriginIsolated

Чтобы определить, вошли ли вы в Cross-Origin Isolated State. Если да, вы можете использовать некоторые ограниченные функции, потому что браузер знает, что вы находитесь в безопасном состоянии.

Кроме того, если вы входите в это состояние, трюк с обходом политики одного источника путем изменения document.domain, упомянутый ранее, больше не будет работать. Браузер не позволит вам больше этого делать.

Чтобы узнать больше о COOP, COEP и Cross-Origin Isolated State, вы можете обратиться к:

Заключение

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

Затем мы поговорили о различных заголовках, начиная с CO:

  1. CORB (Cross-Origin Read Blocking)

  2. CORP (Cross-Origin Resource Policy)

  3. COEP (Cross-Origin-Embedder-Policy)

  4. COOP (Cross-Origin-Opener-Policy)

Если бы мы хотели подвести итог этим четырем понятиям в одном предложении каждое, это могло бы быть так:

  1. CORB: The default mechanism of the browser, mainly to prevent loading unreasonable resources, such as loading HTML with <img>

  2. CORP: An HTTP response header that determines who can load this resource, preventing cross-origin loading of images, videos, or any resources

  3. COEP: An HTTP response header that ensures all resources on the page are loaded legitimately

  4. COOP: An HTTP response header that adds stricter window sharing settings to same-origin

Причина большой длины этой статьи заключается в том, что, с одной стороны, есть много деталей для объяснения, а с другой стороны, она показывает важность концепции Origin для браузера, настолько важную, что требует множества мер для защиты и обеспечения Same-Origin Policy.

После прочтения всех этих вещей о Same-Origin и Cross-Origin давайте переключим тему в следующей статье и рассмотрим классический CSRF.

PreviousВведение в Cross-Origin Resource Sharing (CORS)NextCross-Site Request Forgery (CSRF)

Last updated 8 months ago

Позже автор нашел другие проблемы и успешно достиг RCE (удаленного выполнения кода). Однако эти части не связаны с проблемой настройки CORS, обсуждаемой в этой статье, поэтому я не буду вдаваться в подробности. Если вам интересно, вы можете обратиться к оригинальной статье: .

Для получения дополнительной информации вы можете обратиться к:.

Original report(in Mardarin):

3 января 2018 года команда Google Project Zero опубликовала статью под названием, в которой описывались три атаки, нацеленные на кэш данных CPU:

Примерно через месяц после публичного раскрытия атаки Spectre компанией Google, в феврале 2018 года, они опубликовали пост в блоге, объясняющий, что Chrome сделал для предотвращения этого типа атаки: .

Упомянутое в статье Cross-Site Document Blocking является предшественником CORB. Согласно Chrome , он был официально включен по умолчанию в Chrome для настольной версии 67, что произошло около мая 2018 года. Примерно в то же время он был объединен в спецификацию fetch и стал частью спецификации:

().

Здесь на помощь приходит заголовок HTTP-ответа CORP. CORP, ранее известный как From-Origin, описан в следующей цитате из :

Как упоминалось в предшественника CORP, From-Origin:

The Web platform has no limitations on embedding resources from different origins currently. E.g. an HTML document on can embed an image from without issue. This has led to a number of problems:

Этот термин был кратко упомянут в разделе "Модель безопасности браузера". Начнем с введения в :

В чем разница между этими двумя терминами? Согласно моему пониманию, в статье упоминается:

Note that Chrome uses a specific definition of "site" that includes just the scheme and registered domain. Thus, would be a site, and subdomains like would stay in the same process.

На самом деле, согласно , существует также четвертый тип: Same-Origin-Plus-COEP, но он кажется более сложным, поэтому давайте не будем его изучать пока.

JetBrains IDE Remote Code Execution and Local File Disclosure
AppSec EU 2017 Exploiting CORS Misconfigurations For Bitcoins And Bounties by James Kettle
Asiayo Website CORS Misconfiguration Vulnerability
Reading privileged memory with a side-channel
Reading privileged memory with a side-channel
Interpreting Meltdown & Spectre CPU vulnerabilities
A discussion on processor-level Spectre Attack and Poc analysis
[Chat] Introduction to Spectre & Meltdown vulnerabilities (translation)
Spectre vulnerability example code comments
Google update: Meltdown/Spectre
Mitigating Spectre with Site Isolation in Chrome
Meltdown/Spectre
Chrome Platform Status
CORB: blocking of nosniff and 206 responses
Cross-Origin Read Blocking for Web Developers
Cross-Origin Read Blocking (CORB)
Cross-Origin-Resource-Policy (was: From-Origin) #687
spec
http://example.org
http://corp.invalid
Site Isolation for web developers
Mitigating Spectre with Site Isolation in Chrome
https://google.co.uk
https://maps.google.co.uk
spec
Making your website "cross-origin isolated" using COOP and COEP
Why you need "cross-origin isolated" for powerful features
COEP COOP CORP CORS CORB - CRAP that's a lot of new stuff!
Making postMessage() work for SharedArrayBuffer (Cross-Origin-Embedder-Policy) #4175
Restricting cross-origin WindowProxy access (Cross-Origin-Opener-Policy) #3740
Feature: Cross-Origin Resource Policy