コンテンツ セキュリティ ポリシー

ウェブのセキュリティ モデルは、 同一オリジン ポリシー:コード https://mybank.com のアクセス権は、https://mybank.com のものにのみアクセスできます https://evil.example.com にはアクセスを許可しないようにする必要があります。 各オリジンはウェブの他の場所から分離されているため、デベロッパーは安全に利用できます。 サンドボックス内で開発、プレイできます。理論上は、これは完璧です。イン 攻撃者は、巧妙な方法でシステムを妨害しています。

クロスサイト スクリプティング(XSS) たとえば、サイトをだまして同じオリジンのポリシーをすり抜け、 意図したコンテンツと一緒に悪意のあるコードを配信します。これは非常に ブラウザはページに表示されるすべてのコードを信頼できるものとして信頼するため、 そのページのセキュリティオリジンに 合法的に属します「 XSS クイック リファレンス 古くても典型的な、攻撃者が使用する可能性のある手法の典型的な一分野 不正なコードを挿入してこの信頼を侵害します。攻撃者が ユーザー セッション データはゲームオーバーであり、 秘密にすべき情報が外部に持ち出され、 みんな。できれば、それを避けたいと考えています。

この概要では、リスクを大幅に軽減し、コストを削減できる 最新のブラウザにおける XSS 攻撃の影響: コンテンツ セキュリティ ポリシー(CSP)

要約

  • 許可リストを使用して、許可されるものと許可されないものをクライアントに示す。
  • 使用可能なディレクティブについて説明します。
  • どのようなキーワードが使用されているかを把握する。
  • インラインコードと eval() は有害と見なされます。
  • 適用する前に、サーバーにポリシー違反を報告します。

ソースの許可リスト

XSS 攻撃で悪用される問題は、ブラウザが識別できない問題です。 アプリケーションの一部であるスクリプトと、 検出できます。たとえば、 ページの下部からコードを読み込み このページのオリジンのコンテキストで https://apis.google.com/js/plusone.js。水 そのコードを信頼しますが、ブラウザがコードを認識することは期待できません。 apis.google.com からのコードですが、apis.evil.example.com からのコードは適切ですが、 おそらく違うでしょうブラウザはページにコードを何度かダウンロードし、実行します ソースに関係なく、リクエストの数を抑えられます。

CSP はサーバーが提供するすべてをやみくもに信頼するのではなく、 Content-Security-Policy HTTP ヘッダー。これにより、次の許可リストを作成できます。 コンテンツのソースを作成し、ブラウザに対してそのコンテンツの実行またはレンダリングのみを行うよう指示します。 取得できるからですたとえ攻撃者が スクリプトを挿入すると、スクリプトは許可リストに一致しないため、 実行されます。

Google は、apis.google.com が有効なコードを提供することを信頼しており、Google も信頼できる 指定した場合のみスクリプトを実行できるポリシーを定義し、 次の 2 つのソースのいずれかに由来します

Content-Security-Policy: script-src 'self' https://apis.google.com

実に簡単ですね。ご想像のとおり、script-src は、 特定のページについて、スクリプト関連の権限を制御します。ここでは、 スクリプトの有効なソースとして 'self'https://apis.google.com を 1 つとして指定します。 別のものです。ブラウザは、JavaScript を命令型でダウンロードし、 apis.google.com(HTTPS 経由、および現在のページのオリジンからのもの)。

コンソール エラー: スクリプト「http://evil.example.com/evil.js」の読み込みが拒否されましたコンテンツ セキュリティ ポリシー ディレクティブ: script-src 'self' に違反しているためhttps://apis.google.com

このポリシーを定義すると、ブラウザはエラーをスローする代わりに、 読み込みスクリプトを使用できます。巧妙な攻撃者が サイトにコードを挿入すると、その間はエラー メッセージが表示され、 期待どおりの成果が得られていません。

ポリシーはさまざまなリソースに適用

最も明白なセキュリティ リスクはスクリプト リソースだが、CSP は豊富なリソースと 一連のポリシー ディレクティブを使用して、リソースをきめ細かく制御できます。 ページの読み込みが許可されることを示しますscript-src についてはすでに説明したので、このコンセプトは 明確でなければなりません。

残りのリソース ディレクティブについて簡単に見ていきましょう。以下のリスト レベル 2 におけるディレクティブの状態を表します。レベル 3 の仕様は公開されているが、メジャー レベルではほとんど実装されていない できます。

  • base-uri は、ページの <base> 要素に表示できる URL を制限します。
  • child-src には、ワーカーと埋め込みフレーム コンテンツの URL が一覧表示されます。対象 例: child-src https://youtube.com を使用すると、動画の埋め込みが可能になります。 他のソースからのトラフィックは送信できません。
  • connect-src は、接続できるオリジンを制限します(XHR、 WebSockets、EventSource)。
  • font-src は、ウェブフォントを配信できるオリジンを指定します。Google のウェブ フォントは font-src https://themes.googleusercontent.com で有効にできます。
  • form-action には、<form> タグからの送信に有効なエンドポイントが一覧表示されます。
  • frame-ancestors は、現在のページを埋め込むことができるソースを指定します。 このディレクティブは、<frame> タグ、<iframe> タグ、<embed> タグ、<applet> タグに適用されます。 このディレクティブは、<meta> タグでは使用できず、HTML 以外のタグにのみ適用されます 説明します。
  • frame-src はレベル 2 でサポートが終了しましたが、レベル 3 で復元されています。回答が「いいえ」の場合 これまでと同様に child-src にフォールバックします。
  • img-src は、画像の読み込み元となるオリジンを定義します。
  • media-src は、動画と音声の配信を許可するオリジンを制限します。
  • object-src を使用すると、Flash やその他のプラグインを制御できます。
  • plugin-types は、ページで呼び出せるプラグインの種類を制限します。
  • report-uri は、リクエストされたときにブラウザがレポートを送信する URL を指定します。 コンテンツ セキュリティ ポリシーに違反しています。このディレクティブは <meta> では使用できません できます。
  • style-srcscript-src に対応するスタイルシートです。
  • upgrade-insecure-requests は、ユーザー エージェントに URL スキームの書き換えを指示します。 HTTP から HTTPS に変更します。このディレクティブは、 書き換える必要がある古い URL が除外されます。
  • worker-src は、CSP レベル 3 のディレクティブで、許可する URL を制限します。 ワーカー、共有ワーカー、Service Worker として読み込みます。2017 年 7 月の時点で ディレクティブが 実装に制限があります

デフォルトでは、ディレクティブはワイドオープンです。サービス アカウントに対して特定のポリシーを設定しない場合は、 たとえば font-src の場合、このディレクティブはデフォルトで次のように動作します。 ただし、有効なソースとして * を指定した場合(たとえば、 場所を問わず、制限なく利用できます)。

このデフォルトの動作は、default-src を指定することでオーバーライドできます。 指定します。このディレクティブは、ほとんどのリソースのデフォルト値を定義します。 指定できます。通常、これは、 -src で終わる。default-srchttps://example.com に設定され、失敗する場合 font-src ディレクティブを指定すれば、フォントを https://example.com、他はありません。script-src のみを つまり、画像やフォントなどをそこから 送信元が問いません

次のディレクティブは、フォールバックとして default-src を使用しません。注意点として 設定に失敗した場合、すべて許可した場合と同じです。

  • base-uri
  • form-action
  • frame-ancestors
  • plugin-types
  • report-uri
  • sandbox

これらのディレクティブは、用途に応じて任意の数だけ使用できます。 HTTP ヘッダーにそれぞれをリストし、2 文字目を セミコロンで区切ります。次のすべてをリストに含めてください。 特定の種類の必須リソースを 1 つのディレクティブでまとめます。自分が たとえば、script-src https://host1.com; script-src https://host2.com のような 2 番目のディレクティブは単に無視されます。次のようになります。 次のように、両方のオリジンを有効として正しく指定します。

script-src https://host1.com https://host2.com

たとえば、すべてのリソースを Compute Engine から コンテンツ配信ネットワーク(例: https://cdn.example.net)で、 フレーム内のコンテンツやプラグインが不要な場合、ポリシーは 次のようになります。

Content-Security-Policy: default-src https://cdn.example.net; child-src 'none'; object-src 'none'

実装の詳細

X-WebKit-CSP ヘッダーと X-Content-Security-Policy ヘッダーは、さまざまな形式で表示されます。 チュートリアルをウェブで確認できます。今後は、この接頭辞付きの 使用します。最新のブラウザ(IE を除く)では、プレフィックスなし Content-Security-Policy ヘッダー。このヘッダーを使用する必要があります。

使用するヘッダーに関係なく、ポリシーはページごとに定義されます。 レスポンスが必要なすべてのレスポンスと一緒に HTTP ヘッダーを 確実に保護されますこのように、インフラストラクチャを微調整できるため、 特定のニーズに基づいて特定のページに ポリシーを適用しますおそらく 1 組の +1 ボタンがあるページとないページがあります。その場合は、 必要な場合のみ読み込みます。

各ディレクティブのソースリストは柔軟に使用できます。ソースを指定するには、 スキーム(data:https:)、またはホスト名のみから詳細な範囲まで (example.com、そのホスト上の任意の送信元、つまり、任意のスキーム、任意のポートに一致) 完全修飾 URI(https://example.com:443、HTTPS にのみ一致、 example.com、ポート 443 のみ)。ワイルドカードも使用できますが、あくまでもスキーマとして ポート、またはホスト名の左端の位置 *://*.example.com:* を使用すると、 example.com のすべてのサブドメインに一致します(example.com 自体は対象外)。 接続できます

ソースリストには、次の 4 つのキーワードも指定できます。

  • ご想像のとおり、'none' は何も一致しません。
  • 'self' は現在のオリジンとは一致しますが、サブドメインとは一致しません。
  • 'unsafe-inline' を使用すると、インライン JavaScript と CSS を使用できます。(この点については、 後ほど詳しく説明します)。
  • 'unsafe-eval' では、テキストから JavaScript のメカニズム(eval など)を使用できます。( 追加してください)。

これらのキーワードには一重引用符が必要です。例: script-src 'self'(引用符付き) 現在のホストからの JavaScript の実行を許可します。script-src self (引用符なし)「self」という名前のサーバーからの JavaScript を許可します( 現在のホストなど)が表示されますが、これは意図したとおりではない場合があります。

サンドボックス化

さらに、sandbox という重要なディレクティブが 1 つあります。少し ここで説明した操作とは異なります ページの読み込みに時間がかかることですもし sandbox ディレクティブが存在する場合、ページは読み込まれたものとして扱われます sandbox 属性を指定して <iframe> 内に配置する。これには幅広い ページへの影響: ページを一意のオリジンに強制し、 役立ちます。少しこの記事の範囲を超えていますが、 サンドボックスの有効な属性について詳しくは、 「サンドボックス化」のセクション(HTML5 仕様書)をご覧ください

meta タグ

CSP が推奨する配信メカニズムは HTTP ヘッダーです。有用な場合もありますが ページのマークアップに直接ポリシーを設定できます。これを行うには、<meta> タグを使用して http-equiv 属性:

<meta
  http-equiv="Content-Security-Policy"
  content="default-src https://cdn.example.net; child-src 'none'; object-src 'none'"
/>

frame-ancestorsreport-urisandbox には使用できません。

インラインコードは有害と見なされる

CSP は許可リストのオリジンに基づいていることを明確にする必要があります。これは 特定のリソースセットを処理するようブラウザに指示する明確な方法 残りは拒否できますオリジンベースの許可リストでは ただし、XSS 攻撃の最大の脅威であるインライン スクリプト インジェクションを解決できます。 攻撃者が、悪意のあるファイルを直接含むスクリプトタグを挿入できる場合 ペイロード(<script>sendMyDataToEvilDotCom();</script>)、 ブラウザには、正規のものと 使用します。CSP はこの問題を解決するため、インライン スクリプトを完全に禁止しています。 それが唯一の方法です

この禁止には、script タグに直接埋め込まれたスクリプトだけでなく、 インライン イベント ハンドラと javascript: URL。アプリケーションのコンテンツを 外部ファイルに script タグを追加し、javascript: URL と <a ... onclick="[JAVASCRIPT]"> を適切な addEventListener() 呼び出しに置き換えます。たとえば 次のように書き換えることができます。

<script>
  function doAmazingThings() {
    alert('YOU AM AMAZING!');
  }
</script>
<button onclick="doAmazingThings();">Am I amazing?</button>

次のようになります。

<!-- amazing.html -->
<script src="amazing.js"></script>
<button id="amazing">Am I amazing?</button>

<div style="clear:both;"></div>
// amazing.js
function doAmazingThings() {
  alert('YOU AM AMAZING!');
}
document.addEventListener('DOMContentLoaded', function () {
  document.getElementById('amazing').addEventListener('click', doAmazingThings);
});

書き直したコードには、Terraform で正しく機能させることに加えて、 CSP;どの CSP を使用しているかにかかわらず、すでにベスト プラクティスとなっています。インライン JavaScript は、想定外の方法で構造と動作が混在しています。 外部リソースはブラウザでキャッシュしやすく、 コンパイルと圧縮が容易になりますもっと上手に書けるようになります 外部リソースにコードを移動する場合です

インライン スタイルは、style 属性と style の両方で同じように扱われます。 タグを外部のスタイルシートに統合し、 驚くほど巧妙 データの引き出し方法を確認できます。

インライン スクリプトとスタイルが必要な場合は、有効にできます。 script-src または style-src に、許可されたソースとして 'unsafe-inline' を追加します。 指定します。nonce または hash(以下を参照)を使用することもできますが、使用しないでください。 インライン スクリプトの禁止は、CSP が実現するセキュリティ上の最大のメリットであり、 インライン スタイルを禁止することで、アプリが強化されます。少し すべてのコードを移行した後、正しく機能することを確認する作業を事前に そのようなトレードオフは重要です

どうしても使用する必要がある場合は、

CSP レベル 2 では、インライン スクリプトの下位互換性を 暗号ノンス(番号)を使用して、特定のインライン スクリプトを許可リストに追加する ハッシュを使用できます。面倒に思われるかもしれませんが、 ピンチで締めくくります。

ノンスを使用するには、スクリプトタグにノンス属性を指定します。この値は 1 と一致する必要があります リストにあることを確認します例:

<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
  // Some inline code I can't remove yet, but need to asap.
</script>

次に、nonce- キーワードに追加した script-src ディレクティブにノンスを追加します。

Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'

ノンスは、ページ リクエストごとに再生成する必要があり、 生成 AI です。

ハッシュもほぼ同じように機能します。スクリプトタグにコードを追加する代わりに スクリプト自体の SHA ハッシュを作成し、script-src ディレクティブに追加します。 たとえば、ページに次の内容が含まれているとします。

<script>
  alert('Hello, world.');
</script>

ポリシーは次のようになります。

Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='

ここで注目すべき点がいくつかあります。sha*- 接頭辞でアルゴリズムを指定します ハッシュを生成します。上記の例では、sha256- を使用しています。CSP は sha384-sha512- をサポートしています。ハッシュを生成する際は、ハッシュ値に <script> タグ。また、先頭や末尾などの大文字と小文字、空白文字も 末尾に空白文字がある。

SHA ハッシュの生成について Google で検索すると、どのような形でも解決策が見つかる 多岐にわたります。Chrome 40 以降では、DevTools を開いて ページを再読み込みします。[コンソール] タブには、正しいことを示すエラー メッセージと 各インライン スクリプトの sha256 ハッシュを作成します。

評価も

攻撃者がスクリプトを直接挿入できなくても、 本来なら不活性なテキストを実行可能な JavaScript に変換するようアプリケーションを 実行させておく必要がありますeval()、新規 Function() 、setTimeout([string], ...)setInterval([string], ...) はすべてベクトルで、インジェクト 想定外に悪意のあるものが実行される可能性があります。CSP の すべての経路を完全にブロックする必要があります。

これは、アプリケーションの構築方法にさまざまな影響を与えます。

  • 組み込みの JSON.parse を使用して JSON を解析する必要があります。 eval。ネイティブ JSON オペレーションは IE8 以降のすべてのブラウザで 完全に安全です
  • 現在行っている setTimeout または setInterval の呼び出しをすべて書き換える 文字列ではなくインライン関数で記述します。例:
setTimeout("document.querySelector('a').style.display = 'none';", 10);

次のように記述するとよいでしょう。

setTimeout(function () {
  document.querySelector('a').style.display = 'none';
}, 10);
  • 実行時にインライン テンプレートを使用しない: 多くのテンプレート ライブラリで new Function() をうまく使用することで、実行時のテンプレート生成を高速化しています。Google 動的プログラミングの優れた応用方法ですが、 評価することもあります。フレームワークの中には CSP をすぐにサポートするものがありますが、 eval がない場合に堅牢なパーサーにフォールバックする。 AngularJS の ng-csp ディレクティブ 良い例です

ただし、より適切な選択肢として、利用可能なテンプレート言語を プリコンパイル(Handlebars を実行、 できます。テンプレートを事前にコンパイルすることで、 高速ランタイム実装よりも高速であり 安全性も高まりますeval と テキストから JavaScript への変換がアプリケーションに不可欠な場合は、 有効にするには、script-src に許可されたソースとして 'unsafe-eval' を追加します。 が指示されていますが、使用しないことを強くおすすめします。実行能力の禁止 攻撃者が不正なコードの実行を 確認しましょう

レポート

信頼できないリソースをクライアントサイドでブロックする CSP の機能は、 ユーザーに表示されますが、なんらかの通知が サーバーに送り返されるため、許容可能なバグを 特定して対処できます 検出することです。そのために、 ブラウザから JSON 形式の違反報告を POST 件送信 report-uri ディレクティブ内で指定します。

Content-Security-Policy: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;

レポートは次のようになります。

{
  "csp-report": {
    "document-uri": "http://example.org/page.html",
    "referrer": "http://evil.example.com/",
    "blocked-uri": "http://evil.example.com/evil.js",
    "violated-directive": "script-src 'self' https://apis.google.com",
    "original-policy": "script-src 'self' https://apis.google.com; report-uri http://example.org/my_amazing_csp_report_parser"
  }
}

ここには、問題の特定に役立つ多くの情報が含まれています。 違反の具体的な原因(違反が見つかったページなど) そのページのリファラー(document-uri とは異なり、 (キーのスペルがない場合)、ルールに違反したリソースが ページのポリシー(blocked-uri)、違反した特定のディレクティブ (violated-directive)、ページのポリシーの全文(original-policy)。

レポート専用

CSP を使い始めたばかりの場合は、現在のインフラストラクチャを アプリの状態を確認してから、厳格なポリシーをユーザーに展開します。 完全な導入への足がかりとして、ブラウザに対して Google Cloud の ポリシー違反の報告、制限の適用は行わない。以前の Content-Security-Policy ヘッダーの送信、 Content-Security-Policy-Report-Only ヘッダー。

Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;

レポート専用モードで指定されたポリシーでは、制限付きリソースはブロックされませんが、 指定した場所に違反レポートが送信されます。さらに、 両方のヘッダーを使用して、一方のポリシーを適用し、もう一方のポリシーをモニタリングします。すばらしい アプリケーションの CSP に対する変更の影響を評価するには、 新しいポリシーの報告、違反の報告をモニタリングして、 上げてその効果に問題がなければ、新しいポリシーの適用を開始します。

実際の使用状況

CSP 1 は Chrome、Safari、Firefox で十分に使用できますが、 IE 10 でのサポートGoogle Chat では 詳細は caniuse.com をご覧ください。CSP レベル 2 は、Chrome でリリース以来 バージョン 40 です。Twitter や Facebook などの大規模サイトでこのヘッダーが使用されている (Twitter の事例紹介も一読の価値があります)、この標準版は 独自のサイトへのデプロイを開始できます

アプリケーションのポリシーを作成するための最初のステップは、 リソースを定義します。クラウド移行の方法を まとめられたら、それに基づいてポリシーを設定 提供します。一般的なユースケースをいくつか取り上げて CSP の保護範囲内で最大限にサポートできるということです。

ユースケース 1: ソーシャル メディア ウィジェット

  • Google の +1 ボタン https://apis.google.com からのスクリプトを含み、<iframe> を埋め込みます。 https://plusone.google.com。これら両方を含むポリシーが必要です。 ボタンを埋め込む必要があります。最小限のポリシーは script-src https://apis.google.com; child-src https://plusone.google.com です。さらに Google が提供する JavaScript のスニペットが 作成します。frame-src を使用するレベル 1 ベースのポリシーがある場合 レベル 2 のため、child-src に変更する必要があります。不要になった CSP レベル 3 に属します

  • Facebook の [Like] ボタン 実装オプションがいくつかあります。推奨される方法は <iframe> バージョンです。これはサイトの他の部分から安全にサンドボックス化されているためです。これは、 適切に機能するには、child-src https://facebook.com ディレクティブが必要です。備考 デフォルトでは、Facebook が提供する <iframe> コードが相対 URL を読み込みます。 URL、//facebook.com。これを変更して、HTTPS を明示的に指定します。 https://facebook.com。HTTP を使用する理由はありません。

  • Twitter のツイートボタン スクリプトとフレームへのアクセスに依存しています。これらはどちらも https://platform.twitter.com。(Twitter でも同様に、 default;ローカルにコピー&ペーストするときに HTTPS を指定するようにコードを編集します)。 JavaScript スニペットを移動すれば、script-src https://platform.twitter.com; child-src https://platform.twitter.com で準備は完了です 外部 JavaScript ファイルに記述します。

  • 他のプラットフォームにも同様の要件があり、同様に対処できます。 default-src'none' に設定し、コンソールを監視することをおすすめします。 ウィジェットを動作させるために必要なリソースが決まります

複数のウィジェットを含めるのは簡単です。ポリシーを ディレクティブを使用して、1 つのタイプのすべてのリソースを 1 つの 指定します。3 つすべてのソーシャル メディア ウィジェットが必要な場合、ポリシーは 例:

script-src https://apis.google.com https://platform.twitter.com; child-src https://plusone.google.com https://facebook.com https://platform.twitter.com

ユースケース 2: ロックダウン

あなたは銀行のサイトを運営していて、 自分で作成したリソースのみを読み込むことができます。このシナリオでは すべてを完全にブロックするデフォルト ポリシー(default-src 'none')から始めて、徐々に増やしていきます。

銀行が、CDN からすべての画像、スタイル、スクリプトを https://cdn.mybank.net、XHR 経由で https://api.mybank.com/ に接続し、 さまざまなデータを取り出しますフレームが使用されますが、使用するのは (サードパーティの送信元なし)。サイトに Flash もフォントも 追加できます送信できる最も制限の厳しい CSP ヘッダーは次のとおりです。

Content-Security-Policy: default-src 'none'; script-src https://cdn.mybank.net; style-src https://cdn.mybank.net; img-src https://cdn.mybank.net; connect-src https://api.mybank.com; child-src 'self'

ユースケース 3: SSL のみ

結婚指輪のディスカッション フォーラムの管理者が、すべてのリソースが 安全なチャネル経由でのみ読み込まれるが、コードはあまり作成されない書き換え サードパーティ製フォーラム ソフトウェアの膨大な量が、 インラインスクリプトとスタイルは彼の能力を超えるものです。この場合、次のようにポリシーを設定します。 発効日:

Content-Security-Policy: default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'

default-srchttps: を指定しても、スクリプトとスタイルは ディレクティブがそのソースを自動的に継承することはありません。各ディレクティブは完全に その特定のタイプのリソースのデフォルトが上書きされます。

今後について

コンテンツ セキュリティ ポリシーのレベル 2 はです 受験者の推奨事項。W3C の Web Application Security Working Group 仕様の次のイテレーションの処理がすでに開始されている場合、 コンテンツ セキュリティ ポリシー レベル 3:

今後リリースされる機能に関する ディスカッションに興味がある場合は public-webappsec@ メーリング リストのアーカイブに目を通す 自分で参加することもできます。

フィードバック