Поделиться через


Применение политики безопасности содержимого для ASP.NET Core Blazor

Примечание.

Это не последняя версия этой статьи. В текущем выпуске см. версию этой статьи для .NET 9.

Предупреждение

Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в политике поддержки .NET и .NET Core. В текущем выпуске см. версию этой статьи для .NET 9.

Внимание

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

В текущем выпуске см. версию этой статьи для .NET 9.

В этой статье объясняется, как использовать политику безопасности содержимого (CSP) с приложениями ASP.NET Core Blazor для защиты от определенных типов вредоносных атак, таких как межсайтовые скрипты (XSS) и атаки clickjacking . XSS — это уязвимость безопасности, при которой киберзлоумышленник помещает один или несколько вредоносных скриптов на стороне клиента в отображаемое содержимое приложения. При атаке типа "перехват клика" пользователь обманывается, взаимодействуя с поддельным веб-сайтом, на котором встроено ваше приложение.

CSP помогает защититься от таких атак, сообщая браузеру о допустимом:

  • Источники загруженного содержимого, включая скрипты, таблицы стилей, изображения и подключаемые модули.
  • Действия, выполняемые страницей, с указанием разрешенных целевых URL-адресов форм.
  • Когда ваше приложение может быть внедрено на другой веб-сайт с помощью <frame>, <iframe><object>или <embed> тегов.

При реализации CSP рекомендуется прочитать следующие ресурсы MDN:

Чтобы применить CSP к приложению, разработчик указывает несколько директив безопасности содержимого CSP в одном или нескольких заголовках Content-Security-Policy или тегах <meta>. Рекомендации по применению CSP к приложению в коде C# при запуске см. в разделе ASP.NET Core Запуск Blazor и раздел 'frame-ancestors директивы' далее в этой статье.

Политики оцениваются браузером во время загрузки страницы. Браузер проверяет источники страницы и определяет, соответствуют ли они требованиям директив безопасности содержимого. Если директивы политики не выполняются для ресурса, браузер не загружает ресурс. Например, рассмотрим политику, которая не позволяет использовать сценарии сторонних разработчиков. Если страница содержит тег <script>, в атрибуте src которого указан сторонний источник, браузер предотвращает загрузку сценария.

CSP поддерживается в большинстве современных браузеров для настольных ПК и мобильных устройств, включая Chrome, Microsoft Edge, Firefox, Opera и Safari. CSP рекомендуется для приложений Blazor.

Предупреждение

Реализация CSP сводит к минимуму риск определенных типов угроз безопасности и не гарантирует, что приложение полностью безопасно от XSS и атак clickjacking. Агенты пользователей, как правило, могут позволить пользователям изменять или обходить применение политики с помощью настроек пользователей, закладок, расширений браузера, сторонних дополнений к агенту пользователя и других таких механизмов. Кроме того, поставщики облачных услуг ориентированы только на исправление подмножества атак, а не всех атак, которые могут компрометировать безопасность, таких как SQL-инъекция, межсайтовая подделка запросов (CSRF), ошибочная конфигурация безопасности и атаки типа "отказ в обслуживании" (DoS).

Директивы политики

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

  • base-uri: ограничивает URL-адреса для тега <base> страницы. Укажите self, чтобы отметить, что источник приложения, включая схему и номер порта, является допустимым источником.
  • default-src. Указывает резервный вариант для исходных директив, которые явно не указаны политикой. Укажите self, чтобы отметить, что источник приложения, включая схему и номер порта, является допустимым источником.
  • img-src: указывает допустимые источники для изображений.
    • Укажите data:, чтобы разрешить загрузку изображений с URL-адресов data:.
    • Укажите https:, чтобы разрешить загрузку изображений с конечных точек HTTPS.
  • object-src: указывает допустимые источники для тегов <object>, <embed>и <applet>. Укажите none, чтобы запретить все источники URL-адресов.
  • script-src: указывает допустимые источники для скриптов.
    • Укажите self, чтобы отметить, что источник приложения, включая схему и номер порта, является допустимым источником.
    • В клиентском Blazor приложении:
      • Укажите wasm-unsafe-eval , чтобы разрешить клиентской Blazor среде выполнения Mono функционировать.
      • Укажите любые дополнительные хэши, чтобы разрешить загрузку требуемых скриптов, не связанных с платформой. Например, укажите unsafe-hashes, используя хэш sha256-qnHnQs7NjQNHHNYv/I9cW+I62HzDJjbnyS/OFzqlix0=, чтобы включить встроенный JavaScript для переключателя навигации в компоненте NavMenu.
    • В серверном Blazor приложении укажите хэши, чтобы разрешить загрузку необходимых скриптов.
  • style-src. Указывает допустимые источники для таблиц стилей.
    • Укажите self, чтобы отметить, что источник приложения, включая схему и номер порта, является допустимым источником.
    • Если приложение использует встроенные стили, укажите unsafe-inline, чтобы разрешить их использование.
  • connect-src: ограничивает URL-адреса, которые можно загрузить с помощью интерфейсов скриптов. Указаны источники схемы http:, ws: (протокол WebSocket) и wss: (протокол WebSocket Secure).
  • upgrade-insecure-requests: указывает, что URL-адреса содержимого из небезопасных источников (HTTP) должны быть безопасно приобретены по протоколу HTTPS.
  • base-uri: ограничивает URL-адреса для тега <base> страницы. Укажите self, чтобы отметить, что источник приложения, включая схему и номер порта, является допустимым источником.
  • default-src. Указывает резервный вариант для исходных директив, которые явно не указаны политикой. Укажите self, чтобы отметить, что источник приложения, включая схему и номер порта, является допустимым источником.
  • img-src: указывает допустимые источники для изображений.
    • Укажите data:, чтобы разрешить загрузку изображений с URL-адресов data:.
    • Укажите https:, чтобы разрешить загрузку изображений с конечных точек HTTPS.
  • object-src: указывает допустимые источники для тегов <object>, <embed>и <applet>. Укажите none, чтобы запретить все источники URL-адресов.
  • script-src: указывает допустимые источники для скриптов.
    • Укажите self, чтобы отметить, что источник приложения, включая схему и номер порта, является допустимым источником.
    • В клиентском Blazor приложении:
      • Укажите unsafe-eval , чтобы разрешить клиентской Blazor среде выполнения Mono функционировать.
      • Укажите любые дополнительные хэши, чтобы разрешить загрузку требуемых скриптов, не связанных с платформой.
    • В серверном Blazor приложении укажите хэши, чтобы разрешить загрузку необходимых скриптов.
  • style-src. Указывает допустимые источники для таблиц стилей.
    • Укажите self, чтобы отметить, что источник приложения, включая схему и номер порта, является допустимым источником.
    • Если приложение использует встроенные стили, укажите unsafe-inline, чтобы разрешить их использование.
  • connect-src: ограничивает URL-адреса, которые можно загрузить с помощью интерфейсов скриптов. Указаны источники схемы http:, ws: (протокол WebSocket) и wss: (протокол WebSocket Secure).
  • upgrade-insecure-requests. Указывает, что URL-адреса содержимого из небезопасных источников (HTTP) должны быть безопасно приобретены по протоколу HTTPS.
  • base-uri: ограничивает URL-адреса для тега <base> страницы. Укажите self, чтобы отметить, что источник приложения, включая схему и номер порта, является допустимым источником.
  • default-src. Указывает резервный вариант для исходных директив, которые явно не указаны политикой. Укажите self, чтобы отметить, что источник приложения, включая схему и номер порта, является допустимым источником.
  • img-src: указывает допустимые источники для изображений.
    • Укажите data:, чтобы разрешить загрузку изображений с URL-адресов data:.
    • Укажите https:, чтобы разрешить загрузку изображений с конечных точек HTTPS.
  • object-src: указывает допустимые источники для тегов <object>, <embed>и <applet>. Укажите none, чтобы запретить все источники URL-адресов.
  • script-src: указывает допустимые источники для скриптов.
    • Укажите https://stackpath.bootstrapcdn.com/ источник хоста для Bootstrap скриптов.
    • Укажите self, чтобы отметить, что источник приложения, включая схему и номер порта, является допустимым источником.
    • В клиентском Blazor приложении:
      • Укажите unsafe-eval , чтобы разрешить клиентской Blazor среде выполнения Mono функционировать.
      • Укажите любые дополнительные хэши, чтобы разрешить загрузку требуемых скриптов, не связанных с платформой.
    • В серверном Blazor приложении укажите хэши, чтобы разрешить загрузку необходимых скриптов.
  • style-src. Указывает допустимые источники для таблиц стилей.
    • Укажите источник узла https://stackpath.bootstrapcdn.com/ для таблиц стилей Bootstrap.
    • Укажите self, чтобы отметить, что источник приложения, включая схему и номер порта, является допустимым источником.
    • Укажите unsafe-inline, чтобы разрешить использование встроенных стилей.
  • connect-src: ограничивает URL-адреса, которые можно загрузить с помощью интерфейсов скриптов. Указаны источники схемы http:, ws: (протокол WebSocket) и wss: (протокол WebSocket Secure).
  • upgrade-insecure-requests. Указывает, что URL-адреса содержимого из небезопасных источников (HTTP) должны быть безопасно приобретены по протоколу HTTPS.
  • base-uri: ограничивает URL-адреса для тега <base> страницы. Укажите self, чтобы отметить, что источник приложения, включая схему и номер порта, является допустимым источником.
  • default-src. Указывает резервный вариант для исходных директив, которые явно не указаны политикой. Укажите self, чтобы отметить, что источник приложения, включая схему и номер порта, является допустимым источником.
  • img-src: указывает допустимые источники для изображений.
    • Укажите data:, чтобы разрешить загрузку изображений с URL-адресов data:.
    • Укажите https:, чтобы разрешить загрузку изображений с конечных точек HTTPS.
  • object-src: указывает допустимые источники для тегов <object>, <embed>и <applet>. Укажите none, чтобы запретить все источники URL-адресов.
  • script-src: указывает допустимые источники для скриптов.
    • Укажите https://stackpath.bootstrapcdn.com/ источник хоста для Bootstrap скриптов.
    • Укажите self, чтобы отметить, что источник приложения, включая схему и номер порта, является допустимым источником.
    • В клиентском Blazor приложении:
      • Укажите хэши, чтобы разрешить загрузку необходимых сценариев.
      • Укажите unsafe-eval, чтобы использовать eval() и методы для создания кода из строк.
    • В серверном Blazor приложении укажите хэши, чтобы разрешить загрузку необходимых скриптов.
  • style-src. Указывает допустимые источники для таблиц стилей.
    • Укажите источник узла https://stackpath.bootstrapcdn.com/ для таблиц стилей Bootstrap.
    • Укажите self, чтобы отметить, что источник приложения, включая схему и номер порта, является допустимым источником.
    • Укажите unsafe-inline, чтобы разрешить использование встроенных стилей. Объявление inline необходимо для интерфейса пользователя с целью восстановления подключения между клиентом и сервером после первоначального запроса. В будущих выпусках встроенные стили, возможно, будут удалены, и тогда unsafe-inline больше не потребуется.
  • connect-src: ограничивает URL-адреса, которые можно загрузить с помощью интерфейсов скриптов. Указаны источники схемы http:, ws: (протокол WebSocket) и wss: (протокол WebSocket Secure).
  • upgrade-insecure-requests. Указывает, что URL-адреса содержимого из небезопасных источников (HTTP) должны быть безопасно приобретены по протоколу HTTPS.

Предыдущие директивы поддерживаются всеми браузерами, кроме Microsoft Internet Explorer.

Для получения хэшей SHA для дополнительных встроенных скриптов:

  • Примените CSP, показанный в разделе Применение политики.
  • Доступ к консоли средств разработчика в браузере при локальном запуске приложения. Браузер вычисляет и отображает хэши для заблокированных сценариев при наличии заголовка CSP или тега meta.
  • Скопируйте хэши, предоставленные браузером, в источники script-src. Заключите каждый хэш в одинарные кавычки.

Матрицу поддержки политики безопасности содержимого уровня 2 см. на странице «Можно ли использовать: политика безопасности содержимого уровня 2».

Применение политики

Вы можете применить CSP с помощью следующего:

Чтобы применить политику, используйте <meta> тег:

  • Присвойте атрибуту http-equiv значение Content-Security-Policy.
  • Поместите директивы в значение атрибута content. Директивы следует разделять точкой с запятой (;). Завершающая точка с запятой для последней директивы строки политики не требуется согласно спецификации политики безопасности содержимого уровня 3.
  • Поместите тег <meta> в содержимое <head> непосредственно внутри открывающего тега <head>. Политика оценивается и применяется при синтаксическом анализе разметки CSP, поэтому политика должна отображаться в верхней части <head> разметки, чтобы убедиться, что она применяется ко всем <script> тегам и <link> тегам.

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

Директива frame-ancestors

Директива frame-ancestors указывает допустимые родители, которые могут внедрить страницу с <frame>тегами или <iframe> тегами<object><embed>. Директива frame-ancestors не может применяться через CSP на основе тегов <meta> . Директива должна применяться посредством заголовка ответа. Заголовок ответа CSP может быть добавлен сервером, или код приложения C# может добавлять или обновлять CSP с помощью директивы frame-ancestors.

Blazor Web Apps (.NET 8 или более поздней версии) автоматически включают заголовок ответа, в котором устанавливается значение 'self':

Content-Security-Policy: frame-ancestors 'self'

Чтобы изменить значение по умолчанию на более строгое 'none' и запретить всем родителям внедрять приложение, задайте параметр ContentSecurityFrameAncestorsPolicy в вызове AddInteractiveServerRenderMode в этом Program файле. Следующее действует только при включении сжатия WebSocket (значение ConfigureWebSocketAcceptContext установлено по умолчанию для приложений Blazor).

.AddInteractiveServerRenderMode(o => o.ContentSecurityFrameAncestorsPolicy = "'none'")

В приложениях Blazor Server директива frame-ancestors по умолчанию не добавляется в коллекцию заголовков ответов. Вы можете добавить заголовок CSP вручную с помощью промежуточного слоя в конвейере обработки запросов.

app.Use(async (context, next) =>
{
    context.Response.Headers.Add("Content-Security-Policy", "frame-ancestors 'none'");
    await next();
});

Предупреждение

Избегайте установки значения frame-ancestors директивы 'null', когда включено сжатие WebSocket (сжатие по умолчанию), так как это делает приложение уязвимым для внедрения вредоносных скриптов и атак по перехвату кликов.

Дополнительную информацию см. в разделе CSP: фрейм-предки (документация MDN).

Серверные Blazor приложения

Следующий пример является отправной точкой для дальнейшего развития. В верхней части содержимого<head> примените директивы, описанные в разделе "Директивы политики", а также любые другие директивы, необходимые для спецификации приложения.

Для Blazor Web App или Blazor Server приложений:

<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self' 'wasm-unsafe-eval' 'unsafe-hashes' 
        'sha256-qnHnQs7NjQNHHNYv/I9cW+I62HzDJjbnyS/OFzqlix0=';
    style-src https:;
    connect-src 'self' http: ws: wss:;
    upgrade-insecure-requests;" />

Blazor Web Apps включают встроенный onclick обработчик событий JavaScript в NavMenu компонент, требующий любого из следующих изменений:

  • Добавьте хэш в script-src директиву с ключевым словом unsafe-hashes :

    'unsafe-hashes' 'sha256-qnHnQs7NjQNHHNYv/I9cW+I62HzDJjbnyS/OFzqlix0='
    

    Дополнительные сведения см. в разделе CSP: script-src: небезопасный встроенный скрипт (документация по MDN).

  • Переместите встроенный обработчик событий JavaScript в файл Или модуль JavaScript, который разрешено загружать политикой.

Blazor Web App также имеет компонент ImportMap в содержимом <head>, который отображает встроенный тег карты импорта <script>. Чтобы изменить политику для разрешения загрузки карты импорта, ознакомьтесь с разделом "Разрешение нарушений CSP с использованием интеграции субресурса (SRI) или криптографического nonce".

Для Blazor Server приложений:

<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self';
    style-src 'self';
    connect-src 'self' http: ws: wss:;
    upgrade-insecure-requests">

Для Blazor Server приложений:

<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self' https://stackpath.bootstrapcdn.com/;
    style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com/;
    connect-src 'self' http: ws: wss:;
    upgrade-insecure-requests">

Для Blazor Server приложений:

<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self' https://stackpath.bootstrapcdn.com/ 
        'sha256-34WLX60Tw3aG6hylk0plKbZZFXCuepeQ6Hu7OqRf8PI=';
    style-src 'unsafe-inline' https://stackpath.bootstrapcdn.com/;
    connect-src 'self' http: ws: wss:;
    upgrade-insecure-requests">

Примечание.

Предыдущий хэш SHA256 предназначен для демонстрационных целей. Возможно, потребуется вычислить новый хэш для CSP.

Добавьте дополнительные хэши script-src и style-src, необходимые этому приложению. Во время разработки используйте интерактивное средство или средства разработчика браузера, которые будут вычислять хэши. Например, следующая ошибка консоли средств браузера сообщает о том, что хэш для необходимого сценария не охвачен политикой:

Не удается выполнить встроенный сценарий, так как он нарушает следующую директиву политики безопасности содержимого: "...". Для включения выполнения встроенного сценария требуется ключевое слово "unsafe-inline", хэш ("sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA=") или nonce ("nonce-...").

Конкретный сценарий, связанный с ошибкой, отображается в консоли рядом с ошибкой.

Рекомендации по применению CSP к приложению в коде C# при запуске см. в статье Запуск Blazor ASP.NET Core.

Клиентские Blazor приложения

Следующий пример является отправной точкой для дальнейшего развития. В содержимом<head>примените директивы, описанные в разделе "Директивы политики":

<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self' 'wasm-unsafe-eval';
    style-src 'self';
    connect-src 'none';
    upgrade-insecure-requests">
<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self' 'unsafe-eval';
    style-src 'self';
    connect-src 'none';
    upgrade-insecure-requests">
<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self' 'unsafe-eval' 
        'sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA=';
    style-src 'self';
    connect-src 'none';
    upgrade-insecure-requests">

Примечание.

Хэш sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA= представляет собой скрипт встроенный, используемый для клиентских Blazor программ. Эта возможность может быть удалена в будущем.

<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self' 'unsafe-eval' https://stackpath.bootstrapcdn.com/ 
        'sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA=';
    style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com/;
    upgrade-insecure-requests">
<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self' 'unsafe-eval' https://stackpath.bootstrapcdn.com/ 
        'sha256-v8ZC9OgMhcnEQ/Me77/R9TlJfzOBqrMTW8e1KuqLaqc=' 
        'sha256-If//FtbPc03afjLezvWHnC3Nbu4fDM04IIzkPaf3pH0=' 
        'sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA=';
    style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com/;
    upgrade-insecure-requests">

Добавьте дополнительные хэши script-src и style-src, необходимые этому приложению. Во время разработки используйте интерактивное средство или средства разработчика браузера, которые будут вычислять хэши. Например, следующая ошибка консоли средств браузера сообщает о том, что хэш для необходимого сценария не охвачен политикой:

Не удается выполнить встроенный сценарий, так как он нарушает следующую директиву политики безопасности содержимого: "...". Для включения выполнения встроенного сценария требуется ключевое слово "unsafe-inline", хэш ("sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA=") или nonce ("nonce-...").

Конкретный сценарий, связанный с ошибкой, отображается в консоли рядом с ошибкой.

Разрешение нарушений CSP с помощью функции подресурсной целостности (SRI) или криптографического одноразового токена

Два подхода к устранению нарушений CSP, описанных в следующих двух разделах:

Внедрение целостности субресурса (SRI)

Целостность подресурсов (SRI) позволяет браузерам убедиться, что полученные ресурсы не подверглись изменениям во время передачи. Криптографический хэш, предоставленный на ресурсе, должен соответствовать хэшу, вычисляемого браузером для извлекаемого ресурса, и хэша, указанного в CSP. Совместимость браузера можно оценить на Can I use? Subresource Integrity.

В следующем примере для приложения Blazor Server целостность вычисляется с помощью стороннего инструмента и задается для скрипта Blazor (blazor.server.js) и CSP. Скрипт Blazor не изменяется динамически в этом сценарии и имеет стабильный хэш SHA, поэтому вы можете жестко закодировать integrity значение атрибута.

Предупреждение

crossorigin Задайте атрибут в подресурсе, загруженном из другого источника без общего доступа к ресурсам между источниками (CORS). Если источник приложения отличается от того, где загружается подресурс, требуется заголовок, Access-Control-Allow-Origin позволяющий ресурсу предоставлять общий доступ к источнику запроса или иначеcrossorigin атрибут должен быть применен к тегу подресурса в приложении. В противном случае браузер принимает политику "fail-open" для подресурса, что означает, что подресурс загружается без проверки целостности.

Атрибут crossorigin не добавляется в Blazor<script> тег в следующем примере, так как Blazor скрипт загружается из источника приложения.

Дополнительные сведения см. в разделе "Общий доступ к ресурсам между источниками" и "Целостность субресурсов" (документация по MDN).

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Security-Policy" content="
        base-uri 'self';
        default-src 'self';
        img-src data: https:;
        object-src 'none';
        script-src 'sha256-FyuamsHhg0nWZUnu/f5qrt2DlL1XKt5AX+cgRhtxtfg=';
        style-src https:;
        connect-src 'self' http: ws: wss:;
        upgrade-insecure-requests;" />
    ...
</head>
<body>
    ...
    <script src="_framework/blazor.server.js" 
        integrity="sha256-FyuamsHhg0nWZUnu/f5qrt2DlL1XKt5AX+cgRhtxtfg="></script>
</body>
</html>

В следующем примере для Blazor Web App (.NET 8 или более поздней версии) вычисляется целостность для компонента ImportMap (.NET 9 или более поздней версии). ImportMap Значение целостности вычисляется для каждого запроса приложения, так как ImportMap компонент создает уникальный контент при каждой генерации страницы для ресурсов с отпечатком.

Сформированная карта импорта из компонента ImportMap создается приложением в его исходной точке, поэтому атрибут crossorigin не включен в тег ImportMap. Дополнительные сведения см. в руководстве по CSP MDN: хэши и целостность субресурсов (документация по MDN).

@using System.Security.Cryptography
<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Security-Policy" content="
        base-uri 'self';
        default-src 'self';
        img-src data: https:;
        object-src 'none';
        script-src 'self' 'wasm-unsafe-eval' 'unsafe-hashes' '@integrity'
            'sha256-qnHnQs7NjQNHHNYv/I9cW+I62HzDJjbnyS/OFzqlix0=';
        style-src https:;
        connect-src 'self' http: ws: wss:;
        upgrade-insecure-requests;" />
    ...
    <ImportMap integrity="@integrity" />
    ...
</head>
...
</html>

@code {
    private string? integrity;

    [CascadingParameter]
    public HttpContext? HttpContext { get; set; }

    protected override void OnInitialized()
    {
        var metadata = HttpContext?.GetEndpoint()?.Metadata
            .GetOrderedMetadata<ImportMapDefinition>();
        var utf8 = new System.Text.UTF8Encoding();
        var metadataBytes = utf8.GetBytes(
            metadata?.FirstOrDefault<ImportMapDefinition>()?.ToString()
                .ReplaceLineEndings("\n") ?? string.Empty);
        integrity = 
            $"sha256-{Convert.ToBase64String(SHA256.HashData(metadataBytes))}";
    }
}

До .NET 6 используйте .Replace("\r\n", "\n") вместо вызова ReplaceLineEndings в предыдущем коде.

Примечание.

Если к отрисованному элементу ImportMap компонента должны быть добавлены дополнительные атрибуты <script>, можно передать словарь всех атрибутов компоненту ImportMap в свойстве AdditionalAttributes. Пара integrity имя-значение атрибута передается в словаре вместе с остальными переданными дополнительными атрибутами.

Внедрение криптографического nonce

Криптографический nonce (номер, используемый один раз) позволяет браузерам убедиться, что полученные ресурсы не были изменены в процессе передачи. Одноразовый криптографический nonce, предоставленный в CSP, должен соответствовать nonce, указанному в ресурсе. Совместимость браузера можно оценить на сайте Can I use? Nonce.

В следующем примере для Blazor Web App (.NET 8 или более поздней версии) создается nonce для компонента ImportMap (.NET 9 или более поздней версии) с уникальным значением при каждой загрузке приложения.

Дополнительные сведения см. в руководстве по CSP MDN: Nonces и CSP: script-src: небезопасный встроенный скрипт (документация по MDN).

@using System.Security.Cryptography
<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Security-Policy" content="
        base-uri 'self';
        default-src 'self';
        img-src data: https:;
        object-src 'none';
        script-src 'self' 'wasm-unsafe-eval' 'unsafe-hashes' 'nonce-@nonce' 
            'sha256-qnHnQs7NjQNHHNYv/I9cW+I62HzDJjbnyS/OFzqlix0=';
        style-src https:;
        connect-src 'self' http: ws: wss:;
        upgrade-insecure-requests;" />
    ...
    <ImportMap nonce="@nonce" />
    ...
</head>
...
</html>

@code {
    private string? nonce;

    protected override void OnInitialized()
    {
        using (var rng = RandomNumberGenerator.Create())
        {
            var nonceBytes = new byte[32];
            rng.GetBytes(nonceBytes);
            nonce = Convert.ToBase64String(nonceBytes);
        }
    }
}

Примечание.

Если к отрисованному элементу ImportMap компонента должны быть добавлены дополнительные атрибуты <script>, можно передать словарь всех атрибутов компоненту ImportMap в свойстве AdditionalAttributes. Пара nonce name-value передается в словаре с остальными дополнительными переданными атрибутами.

Примените CSP в средах, отличных от Development

Когда CSP применяется к Blazor содержимому приложения <head> , он вмешивается в локальное тестирование в Development среде. Например, ссылка на браузер и скрипт обновления браузера не загружались. В следующих примерах показано, как применить тег CSP <meta> в средах, отличных от Development сред.

Примечание.

Примеры, приведенные в этом разделе, не показывают полный тег <meta> для CSPs. <meta> Полные теги находятся в подразделах раздела "Применить политику" ранее в этой статье.

Доступны три общих подхода:

  • Примените CSP через App компонент, который применяет CSP ко всем макетам приложения.
  • Если необходимо применить CSP к различным областям приложения, например, пользовательскую CSP только для страниц администрирования, примените CSP на основе каждого макета с помощью тега <HeadContent>. Для полной эффективности каждый файл макета приложения должен принять подход.
  • Служба размещения или сервер могут предоставить CSP через Content-Security-Policy заголовок, добавляемый к исходящим ответам приложения. Так как этот подход зависит от размещения службы или сервера, он не рассматривается в следующих примерах. Если вы хотите применить этот подход, обратитесь к документации по поставщику услуг размещения или серверу.

Blazor Web App Подходы

В компоненте App (Components/App.razor) внедрить IHostEnvironment:

@inject IHostEnvironment Env

В содержимом App компонента <head> примените CSP, если он не находится в Development среде:

@if (!Env.IsDevelopment())
{
    <meta ...>
}

Кроме того, примените политики безопасности содержимого для каждого макета в папке Components/Layout, как показано в следующем примере. Убедитесь, что каждый макет определяет Политику безопасности контента (CSP).

@inject IHostEnvironment Env

@if (!Env.IsDevelopment())
{
    <HeadContent>
        <meta ...>
    </HeadContent>
}

Blazor WebAssembly способы использования приложения

В компоненте App (App.razor) внедрить IWebAssemblyHostEnvironment:

@using Microsoft.AspNetCore.Components.WebAssembly.Hosting
@inject IWebAssemblyHostEnvironment Env

В содержимом App компонента <head> примените CSP, если он не находится в Development среде:

@if (!Env.IsDevelopment())
{
    <HeadContent>
        <meta ...>
    </HeadContent>
}

Кроме того, используйте предыдущий код, но примените политики безопасности контента на основе макета в папке Layout. Убедитесь, что каждый макет определяет Политику безопасности контента (CSP).

Ограничения метатегов

Политика тегов <meta> не поддерживает следующие директивы:

Для поддержки предыдущих директив используйте заголовок с именем Content-Security-Policy. Строка директивы — это значение заголовка.

Тестирование политики и получение отчетов о нарушениях

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

Чтобы протестировать политику в течение определенного периода времени без применения директив политики, задайте для атрибута<meta> тега http-equiv или заголовка политики на основе заголовков значение Content-Security-Policy-Report-Only. Отчеты о сбоях отправляются как документы JSON по указанному URL-адресу. Для получения дополнительной информации см. веб-документы MDN: Content-Security-Policy-Report-Only.

Для получения информации об отчетах о нарушениях, когда политика активна, см. следующие статьи:

Хотя report-uri больше не рекомендуется использовать, обе директивы следует использовать до тех пор, пока report-to не будут поддерживаться всеми основными браузерами. Не используйте исключительно report-uri, поскольку поддержка report-uri может быть удалена из браузеров в любое время. Удалите поддержку report-uri в политиках, если report-to полностью поддерживается. Для отслеживания внедрения report-to см. Can I use: report-to.

Протестируйте и обновляйте политику приложения при каждом выпуске новой версии.

Устранение неполадок

  • Ошибки отображаются в консоли средств разработчика браузера. Браузеры предоставляют сведения о следующем:
    • Элементы, которые не соответствуют политике.
    • Как изменить политику, чтобы разрешить заблокированный элемент.
  • Политика полностью эффективна, только если браузер клиента поддерживает все включенные директивы. Сведения о текущей матрице поддержки браузера см. в статье "Можно ли использовать: Content-Security-Policy".

Дополнительные ресурсы