ASP.NET Core Blazor のコンテンツ セキュリティ ポリシーを適用する

注意

これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。

重要

この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。

現在のリリースについては、この記事の .NET 8 バージョンを参照してください。

この記事では、ASP.NET Core Blazor アプリでコンテンツ セキュリティ ポリシー (CSP) を使用して、クロスサイト スクリプティング (XSS) 攻撃から保護する方法について説明します。

クロスサイト スクリプティング (XSS) は、アプリのレンダリングされたコンテンツに攻撃者が 1 つ以上の悪意のあるクライアント側スクリプトを配置するセキュリティの脆弱性です。 CSP は、ブラウザーに次の有効な内容を通知することで、XSS 攻撃から保護することができます。

  • スクリプト、スタイルシート、イメージ、プラグインなど、読み込まれたコンテンツのソース。
  • ページによって実行され、フォームの許可された URL ターゲットを指定するアクション。

CSP をアプリに適用するために、開発者は 1 つ以上の Content-Security-Policy ヘッダーまたは <meta> タグに複数の CSP コンテンツ セキュリティ "ディレクティブ" を指定します。 起動時に C# コードでアプリに CSP を適用する方法のガイダンスについては、「ASP.NET Core Blazor の起動」をご覧ください。

ポリシーは、ページの読み込み中にブラウザーによって評価されます。 ブラウザーによりページのソースが検査され、コンテンツ セキュリティ ディレクティブの要件を満たしているかどうかが判断されます。 リソースのポリシー ディレクティブが満たされていない場合、ブラウザーでリソースが読み込まれません。 たとえば、サードパーティのスクリプトを許可しないポリシーについて考えてみます。 ページの src 属性にサードパーティから発生した <script> タグが含まれている場合、ブラウザーによってスクリプトの読み込みが禁止されます。

CSP は、Chrome、Microsoft Edge、Firefox、Opera、Safari など、最新のデスクトップおよびモバイル ブラウザーのほとんどでサポートされています。 CSP は、Blazor アプリで推奨されています。

ポリシー ディレクティブ

最小限として、Blazor アプリの次のディレクティブとソースを指定します。 必要に応じて、ディレクティブとソースを追加してください。 次のディレクティブは、この記事の「ポリシーの適用」セクションで使用されます。その項では、Blazor アプリのセキュリティ ポリシーの例を提供しています。

  • base-uri: ページの <base> タグの URL を制限します。 self を指定して、スキームやポート番号など、アプリの配信元が有効なソースであることを示します。
  • default-src: ポリシーによって明示的に指定されていないソース ディレクティブのフォールバックを示します。 self を指定して、スキームやポート番号など、アプリの配信元が有効なソースであることを示します。
  • img-src: 画像の有効なソースを示します。
    • data: の URL からの画像の読み込みを許可するには data: を指定します。
    • HTTPS のエンドポイントからの画像の読み込みを許可するには https: を指定します。
  • object-src: <object><embed><applet> タグの有効なソースを示します。 すべての URL ソースを禁止するには、none を指定します。
  • script-src: スクリプトの有効なソースを示します。
    • self を指定して、スキームやポート番号など、アプリの配信元が有効なソースであることを示します。
    • クライアントサイド Blazor アプリ内は以下のようになっています。:
      • クライアントサイド Blazor Mono ランタイムの機能を許可するように wasm-unsafe-eval を指定します。
      • 必要な "非フレームワーク スクリプト" の読み込みを許可する追加のハッシュを指定します。
    • サーバーサイド Blazor アプリでは、必要なスクリプトの読み込みを許可するハッシュを指定します。
  • style-src: スタイルシートの有効なソースを示します。
    • self を指定して、スキームやポート番号など、アプリの配信元が有効なソースであることを示します。
    • アプリでインライン スタイルを使用する場合は、インライン スタイルの使用を許可するように unsafe-inline を指定します。
  • upgrade-insecure-requests: セキュリティで保護されていない (HTTP) ソースからのコンテンツ URL を HTTPS 経由で安全に取得する必要があることを示します。
  • base-uri: ページの <base> タグの URL を制限します。 self を指定して、スキームやポート番号など、アプリの配信元が有効なソースであることを示します。
  • default-src: ポリシーによって明示的に指定されていないソース ディレクティブのフォールバックを示します。 self を指定して、スキームやポート番号など、アプリの配信元が有効なソースであることを示します。
  • img-src: 画像の有効なソースを示します。
    • data: の URL からの画像の読み込みを許可するには data: を指定します。
    • HTTPS のエンドポイントからの画像の読み込みを許可するには https: を指定します。
  • object-src: <object><embed><applet> タグの有効なソースを示します。 すべての URL ソースを禁止するには、none を指定します。
  • script-src: スクリプトの有効なソースを示します。
    • self を指定して、スキームやポート番号など、アプリの配信元が有効なソースであることを示します。
    • クライアントサイド Blazor アプリ内は以下のようになっています。:
      • クライアントサイド Blazor Mono ランタイムの機能を許可するように unsafe-eval を指定します。
      • 必要な "非フレームワーク スクリプト" の読み込みを許可する追加のハッシュを指定します。
    • サーバーサイド Blazor アプリでは、必要なスクリプトの読み込みを許可するハッシュを指定します。
  • style-src: スタイルシートの有効なソースを示します。
    • self を指定して、スキームやポート番号など、アプリの配信元が有効なソースであることを示します。
    • アプリでインライン スタイルを使用する場合は、インライン スタイルの使用を許可するように unsafe-inline を指定します。
  • upgrade-insecure-requests: セキュリティで保護されていない (HTTP) ソースからのコンテンツ URL を HTTPS 経由で安全に取得する必要があることを示します。
  • base-uri: ページの <base> タグの URL を制限します。 self を指定して、スキームやポート番号など、アプリの配信元が有効なソースであることを示します。
  • default-src: ポリシーによって明示的に指定されていないソース ディレクティブのフォールバックを示します。 self を指定して、スキームやポート番号など、アプリの配信元が有効なソースであることを示します。
  • img-src: 画像の有効なソースを示します。
    • data: の URL からの画像の読み込みを許可するには data: を指定します。
    • HTTPS のエンドポイントからの画像の読み込みを許可するには https: を指定します。
  • object-src: <object><embed><applet> タグの有効なソースを示します。 すべての URL ソースを禁止するには、none を指定します。
  • script-src: スクリプトの有効なソースを示します。
    • ブートストラップ スクリプトの https://stackpath.bootstrapcdn.com/ ホスト ソースを指定します。
    • self を指定して、スキームやポート番号など、アプリの配信元が有効なソースであることを示します。
    • クライアントサイド Blazor アプリ内は以下のようになっています。:
      • クライアントサイド Blazor Mono ランタイムの機能を許可するように unsafe-eval を指定します。
      • 必要な "非フレームワーク スクリプト" の読み込みを許可する追加のハッシュを指定します。
    • サーバーサイド Blazor アプリでは、必要なスクリプトの読み込みを許可するハッシュを指定します。
  • style-src: スタイルシートの有効なソースを示します。
    • ブートストラップ スタイルシートの https://stackpath.bootstrapcdn.com/ ホスト ソースを指定します。
    • self を指定して、スキームやポート番号など、アプリの配信元が有効なソースであることを示します。
    • インライン スタイルの使用を許可するには unsafe-inline を指定します。
  • upgrade-insecure-requests: セキュリティで保護されていない (HTTP) ソースからのコンテンツ URL を HTTPS 経由で安全に取得する必要があることを示します。
  • base-uri: ページの <base> タグの URL を制限します。 self を指定して、スキームやポート番号など、アプリの配信元が有効なソースであることを示します。
  • default-src: ポリシーによって明示的に指定されていないソース ディレクティブのフォールバックを示します。 self を指定して、スキームやポート番号など、アプリの配信元が有効なソースであることを示します。
  • img-src: 画像の有効なソースを示します。
    • data: の URL からの画像の読み込みを許可するには data: を指定します。
    • HTTPS のエンドポイントからの画像の読み込みを許可するには https: を指定します。
  • object-src: <object><embed><applet> タグの有効なソースを示します。 すべての URL ソースを禁止するには、none を指定します。
  • script-src: スクリプトの有効なソースを示します。
    • ブートストラップ スクリプトの https://stackpath.bootstrapcdn.com/ ホスト ソースを指定します。
    • self を指定して、スキームやポート番号など、アプリの配信元が有効なソースであることを示します。
    • クライアントサイド Blazor アプリ内は以下のようになっています。:
      • 必要なスクリプトの読み込みを許可するハッシュを指定します。
      • eval() および文字列からコードを作成するメソッドを使用するには、unsafe-eval を指定します。
    • サーバーサイド Blazor アプリでは、必要なスクリプトの読み込みを許可するハッシュを指定します。
  • style-src: スタイルシートの有効なソースを示します。
    • ブートストラップ スタイルシートの https://stackpath.bootstrapcdn.com/ ホスト ソースを指定します。
    • self を指定して、スキームやポート番号など、アプリの配信元が有効なソースであることを示します。
    • インライン スタイルの使用を許可するには unsafe-inline を指定します。 初期要求後にクライアントとサーバーを再接続するには、UI のためのインライン宣言が必要です。 今後のリリースでは、unsafe-inline が不要になるように、インライン スタイルが削除される可能性があります。
  • upgrade-insecure-requests: セキュリティで保護されていない (HTTP) ソースからのコンテンツ URL を HTTPS 経由で安全に取得する必要があることを示します。

上記のディレクティブは、Microsoft Internet Explorer 以外のすべてのブラウザーでサポートされています。

追加のインライン スクリプトの SHA ハッシュを取得するには:

  • ポリシーの適用」セクションに示されている CSP を適用します。
  • アプリをローカルで実行しながら、ブラウザーの開発者ツールのコンソールにアクセスします。 CSP ヘッダーまたは meta タグが存在する場合、ブラウザーではブロックされたスクリプトのハッシュが計算されて表示されます。
  • ブラウザーによって提供されるハッシュを script-src ソースにコピーします。 単一引用符を使用して各ハッシュを囲みます。

コンテンツ セキュリティ ポリシー レベル 2 のブラウザー サポート マトリックスは、「Can I use: Content Security Policy Level 2」(私は使用できますか? コンテンツ セキュリティ ポリシー レベル 2) を参照してください。

ポリシーの適用

<meta> タグを使用してポリシーを適用します。

  • http-equiv 属性の値は Content-Security-Policy に設定します。
  • content 属性値にディレクティブを配置します。 各ディレクティブをセミコロン (;) で区切ります。
  • meta タグを、必ず <head>コンテンツの中に配置します。

次のセクションにポリシーの例を示します。 これらの例は、Blazor のリリースごとにこの記事でバージョン管理されています。 リリースに適したバージョンを使用するには、この Web ページの [バージョン] ドロップダウン セレクターを使用してドキュメントのバージョンを選択してください。

サーバーサイド 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';
               style-src 'self';
               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 https://stackpath.bootstrapcdn.com/ 
                          'self';
               style-src https://stackpath.bootstrapcdn.com/
                         'self' 
                         'unsafe-inline';
               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 https://stackpath.bootstrapcdn.com/ 
                          'self' 
                          'sha256-34WLX60Tw3aG6hylk0plKbZZFXCuepeQ6Hu7OqRf8PI=';
               style-src https://stackpath.bootstrapcdn.com/
                         'self' 
                         'unsafe-inline';
               upgrade-insecure-requests;">

アプリで必要な場合に、さらに script-srcstyle-src ハッシュを追加します。 開発時には、オンライン ツールまたはブラウザー開発者ツールを使用して、ハッシュが自動的に計算されるようにします。 たとえば、次のブラウザー ツール コンソールのエラーは、必要なスクリプトに対するハッシュがポリシーでカバーされていないことを報告するものです。

次のコンテンツ セキュリティ ポリシー ディレクティブに違反しているため、インライン スクリプトの実行が拒否されました: "..."。 インライン実行を有効にするには、'unsafe-inline' キーワード、ハッシュ ('sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA=')、または nonce ('nonce-...') のいずれかが必要です。

エラーに関連付けられている特定のスクリプトが、コンソール内でエラーの隣に表示されます。

クライアントサイド 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';
               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';
               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' 
                          'sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA=' 
                          'unsafe-eval';
               style-src 'self';
               upgrade-insecure-requests;">

Note

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 https://stackpath.bootstrapcdn.com/ 
                          'self' 
                          'sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA=' 
                          'unsafe-eval';
               style-src https://stackpath.bootstrapcdn.com/
                         'self'
                         'unsafe-inline';
               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 https://stackpath.bootstrapcdn.com/ 
                          'self' 
                          'sha256-v8ZC9OgMhcnEQ/Me77/R9TlJfzOBqrMTW8e1KuqLaqc=' 
                          'sha256-If//FtbPc03afjLezvWHnC3Nbu4fDM04IIzkPaf3pH0=' 
                          'sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA=' 
                          'unsafe-eval';
               style-src https://stackpath.bootstrapcdn.com/
                         'self'
                         'unsafe-inline';
               upgrade-insecure-requests;">

アプリで必要な場合に、さらに script-srcstyle-src ハッシュを追加します。 開発時には、オンライン ツールまたはブラウザー開発者ツールを使用して、ハッシュが自動的に計算されるようにします。 たとえば、次のブラウザー ツール コンソールのエラーは、必要なスクリプトに対するハッシュがポリシーでカバーされていないことを報告するものです。

次のコンテンツ セキュリティ ポリシー ディレクティブに違反しているため、インライン スクリプトの実行が拒否されました: "..."。 インライン実行を有効にするには、'unsafe-inline' キーワード、ハッシュ ('sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA=')、または nonce ('nonce-...') のいずれかが必要です。

エラーに関連付けられている特定のスクリプトが、コンソール内でエラーの隣に表示されます。

Development 環境での CSP の適用

Blazor アプリの <head> コンテンツに CSP を適用すると、Development 環境でのローカル テストが妨げられます。 たとえば、ブラウザー リンクとブラウザー更新スクリプトの読み込みに失敗します。 次の例は、Development 以外の環境で CSP の <meta> タグを適用する方法を示しています。

Note

このセクションの例には、CSP 用の完全な <meta> タグは示していません。 完全な <meta> タグについては、この記事の「ポリシーの適用」セクションのサブセクションを参照してください。

次の 3 つの一般的なアプローチが利用できます。

  • App コンポーネントを介して CSP を適用します。これにより、アプリのすべてのレイアウトに CSP が適用されます。
  • アプリのさまざまな領域 (管理者ページ専用のカスタム CSP など) に CSP を適用する必要がある場合は、<HeadContent> タグを使用してレイアウトごとに CSP を適用します。 完全な効果を得るには、すべてのアプリ レイアウト ファイルでこのアプローチを採用する必要があります。
  • ホスティング サービスまたはサーバーでは、アプリの送信応答を追加した Content-Security-Policy ヘッダーを介して CSP を提供できます。 このアプローチは、ホスティング サービスまたはサーバーごとに異なるため、次の例では取り上げていません。 このアプローチを採用する場合は、ご利用のホスティング サービス プロバイダーまたはサーバーのドキュメントを参照してください。

Blazor Web App のアプローチ

App コンポーネント (Components/App.razor) に、IHostEnvironment を挿入します。

@inject IHostEnvironment Env

Development 環境にない場合は、App コンポーネントの <head> コンテンツで CSP を適用します。

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

あるいは、次の例に示すように、Components/Layout フォルダー内のレイアウトごとに CSP を適用します。 すべてのレイアウトで 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

Development 環境にない場合は、App コンポーネントの <head> コンテンツで CSP を適用します。

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

あるいは、上記のコードを使用します。ただし、CSP は Layout フォルダー内のレイアウトごとに適用します。 すべてのレイアウトで CSP が指定されていることを確認します。

Meta タグに関する制限事項

<meta> タグ ポリシーでは、次のディレクティブがサポートされていません。

上記のディレクティブをサポートするには、Content-Security-Policy という名前のヘッダーを使用します。 ディレクティブ文字列は、ヘッダーの値です。

ポリシーをテストして違反レポートを受信する

テストは、初期ポリシーを作成するときに、サードパーティのスクリプトが誤ってブロックされていないことを確認するのに役立ちます。

ポリシー ディレクティブを適用せずに一定期間にわたってポリシーをテストするには、ヘッダーベースのポリシーの <meta> タグの http-equiv 属性またはヘッダー名を Content-Security-Policy-Report-Only に設定します。 エラー レポートは、JSON ドキュメントとして指定された URL に送信されます。 詳細については、MDN Web ドキュメント:「Content-Security-Policy-Report-Only」を参照してください。

ポリシーがアクティブになっている間に違反を報告するには、次の記事を参照してください。

report-uri の使用は推奨されなくなりましたが、すべての主要なブラウザーで report-to がサポートされるようになるまで、両方のディレクティブを使用する必要があります。 report-uri のサポートは、ブラウザーから "常に" 削除される可能性があるため、report-uri を排他的に使用しないでください。 report-to が完全にサポートされたら、ポリシー内の report-uri のサポートを削除します。 report-to が導入されたかどうかを追跡する方法については、「Can I use: report-to」(私は使用できますか? report-to) を参照してください。

アプリがリリースされるたびにポリシーをテストして更新してください。

トラブルシューティング

  • エラーは、ブラウザーの開発者ツールのコンソールに表示されます。 ブラウザーには次に関する情報が表示されます。
    • ポリシーに準拠していない要素。
    • ブロックされた項目を許可するようにポリシーを変更する方法。
  • ポリシーが完全に有効になるのは、含まれているすべてのディレクティブがクライアントのブラウザーでサポートされている場合のみです。 現在のブラウザーのサポート マトリックスについては、「Can I use: Content-Security-Policy」(私は使用できますか? Content-Security-Policy) を参照してください。

その他の技術情報