World Wide Web のセキュリティ ポリシーは同一生成元ポリシーに基づいています。たとえば、www.jb51.net のコードは www.jb51.net のデータにのみアクセスできますが、http://www.baidu.com にアクセスする権限はありません。各オリジンはネットワークの残りの部分から分離されており、開発者にとって安全なサンドボックスが作成されます。これは理論的には完璧ですが、攻撃者はこのシステムを侵害する巧妙な方法を発見しました。
これは XSS クロスサイト スクリプティング攻撃であり、偽のコンテンツやおとりクリックによって同一生成元ポリシーをバイパスします。これは大きな問題であり、攻撃者がコードの挿入に成功すると、かなりの量のユーザー データが漏洩する可能性があります。
ここで、このリスクを軽減するための新しく効果的なセキュリティ防御戦略、つまりコンテンツ セキュリティ ポリシー (CSP) を紹介します。
ソース ホワイトリスト
XSS 攻撃の核心は、スクリプトがサードパーティによって挿入されたものなのか、それとも実際にアプリケーションの一部なのかをブラウザが区別できないことです。たとえば、Google 1 ボタンは https://apis.google.com/js/plusone.js からコードをロードして実行しますが、ブラウザ上の画像からコードが実際に apis.google からのものであるかどうかを判断することはできません。 .com 、こちらも apis.evil.example.com から。ブラウザーは、その発信元に関係なく、ページ リクエストで任意のコードをダウンロードして実行します。
CSP は、Content-Security-Policy HTTP ヘッダーを定義して、信頼できるソースのホワイトリストを作成できるようにします。これにより、ブラウザーは、サーバーによって提供されるすべてのコンテンツを盲目的に信頼するのではなく、これらのソースからのリソースのみを実行およびレンダリングします。攻撃者がスクリプトを挿入する脆弱性を見つけたとしても、そのソースがホワイトリストに含まれていないため、そのスクリプトは実行されません。
上記の Google 1 ボタンを例にとると、apis.google.com と自分自身が有効なコードを提供していると考えられるため、ブラウザーが次の 2 つのいずれかのスクリプトのみを実行できるようにするポリシーを定義できます。ソース。
Content-Security-Policy:script-src 'self' https://apis.google.com
とても簡単ですね。 script-src は、指定されたページのスクリプト関連のアクセス許可を制御できます。このようにすると、ブラウザは http://apis.google.com とこのページ自体からのみスクリプトをダウンロードして実行します。
この戦略を定義すると、ブラウザーは挿入されたコードを検出するとエラーをスローします (どのブラウザーであるかに注意してください)。
コンテンツ セキュリティ ポリシーは、一般的に使用されるすべてのリソースに適用されます
スクリプト リソースは最も明白なセキュリティ リスクですが、CSP は、ページがさまざまな種類のリソースの読み込みを制御できるようにする豊富な命令セットも提供します。次のタイプ:
content-src: 接続のタイプを制限します (XHR、WebSocket、EventSource など)。
font-src: Web フォントのソースを制御します。たとえば、Google の Web フォントは、font-src https://themes.googleusercontent.com を通じて使用できます。
frame-src: 埋め込み可能なフレームのソースをリストします。たとえば、frame-src https://youtube.com では YouTube ビデオの埋め込みのみが許可されます。 。
img-src: ロード可能な画像のソースを定義します。
media-src: ビデオおよびオーディオ ソースを制限します。
object-src: Flash およびその他のプラグインのソースを制限します。
style-src: Script-src に似ていますが、CSS ファイルにのみ適用されます。
デフォルトでは、すべての設定が制限なくオンになっています。複数のディレクティブをセミコロンで区切ることができますが、script-src https://host1.com;script-src https://host2.com の形式では、2 番目のディレクティブは無視されます。正しい書き方は script-src https://host1.com https://host2.com です。
たとえば、コンテンツ配信ネットワーク (CDN、https://cdn.example.net など) からすべてのリソースをロードする必要があるアプリケーションがあり、それを必要としないコンテンツが存在しないことがわかっている場合、フレームまたはプラグインの場合、戦略は次のようになります。
Content-Security-Policy:default-src https://cdn.example.net;この例で使用する
詳細
HTTP ヘッダーは Content-Security-Policy ですが、最新のブラウザはすでにプレフィックスによるサポートを提供しています。Firefox は x-Content-Security-Policy を使用し、WebKit は X-WebKit-CSP を使用します。将来的には、統一規格への移行が段階的に行われる予定です。
各ページに応じて戦略を設定できるため、柔軟性が高くなります。サイトの一部のページには Google 1 ボタンがある場合もあれば、そうでないページもあるためです。
各ディレクティブのソース リストは非常に柔軟で、パターン (data:、https:) を指定することも、ホスト名を範囲 (example.com で指定することもできます。これは、任意のオリジン、任意のパターン、および任意のポートに一致します)ホスト上の )、または完全な URI (https://example.com:443、具体的には https プロトコル、example.com ドメイン名、ポート 443) を指定します。
ソース リストで使用できるキーワードはさらに 4 つあります。
"none": 何も一致しないと予想されるかもしれません
"self": 現在のソースと同じですが、サブドメインはありません
"unsafe- inline ": インライン Javascript と CSS を許可します
"unsafe-eval": eval などのテキストから JS へのメカニズムを許可します
これらのキーワードは引用符で囲む必要があることに注意してください。
サンドボックス
ここで議論する価値のあるもう 1 つのディレクティブ、サンドボックスがあります。これは他の命令と多少矛盾していますが、ページがロードできるリソースではなく、主にページ上で実行されるアクションを制御します。この属性が設定されている場合、ページはサンドボックス属性が設定されたフレームのように動作します。これは、フォームの送信を妨げるなど、ページに幅広い影響を及ぼします。これはこの記事の範囲を少し超えていますが、HTML5 仕様の「サンドボックス フラグ設定」の章で詳細を確認できます。
有害なインライン コード
CSP はソースのホワイトリストに基づいていますが、XSS 攻撃の最大の原因であるインライン スクリプト インジェクションを解決することはできません。攻撃者が有害なコードを含むスクリプト タグ (
) を挿入できる場合、ブラウザーにはこのタグを区別する適切なメカニズムがありません。 CSP は、インライン スクリプトを完全に無効にすることによってのみこの問題を解決できます。 この禁止事項には、スクリプトに埋め込まれたスクリプト タグだけでなく、インライン イベント ハンドラーや javascrpt: URL も含まれます。 script タグの内容を外部ファイルに配置し、javascript: と
を適切な addEventListener メソッドに置き換える必要があります。たとえば、次の形式:
Am IAmazing?
を次の形式に書き換えることができます:
私はすごいですか?
//Amazing.js
function doAmazingThings() {
alert('YOU AM AMAZING!');
}
ドキュメント。 addEventListener('DOMContentReady', function () {
document.getElementById('amazing')
.addEventListener('click', doAmazingThings);
});
CSP を使用するかどうかに関係なく、上記のコードには実際にはさらに大きな利点があります。インライン JavaScript は構造と動作を完全に混合しているため、これを行うべきではありません。さらに、外部リソースはブラウザーでキャッシュしやすく、開発者にとって理解しやすく、コンパイルや圧縮も容易です。外部コードを使用すると、より良いコードを作成できます。
インライン スタイルは同じ方法で処理する必要があり、スタイル属性とスタイル タグの両方を外部スタイル シートに抽出する必要があります。これにより、あらゆる種類の魔法のような方法によるデータ漏洩が防止されます。
インライン スクリプトとスタイルが必要な場合は、script-src または style-src 属性に「unsafe-inline」値を設定できます。ただし、インライン スクリプトを無効にすることは、CSP によって提供される最大のセキュリティ保証であり、アプリケーションの安全性と堅牢性を高めることができます。それはトレードオフですが、それだけの価値は十分にあります。
Eval
攻撃者がスクリプトを直接挿入できない場合でも、アプリケーションをだまして挿入されたテキストを実行可能なスクリプトに変換し、それ自体を実行させる可能性があります。 eval() 、 newFunction() 、 setTimeout([string], ...) 、および setInterval([string], ...) はすべて、この危険を媒介する可能性があります。このリスクに対する CSP の戦略は、これらのベクトルを完全にブロックすることです。
これは、アプリケーションの構築方法にいくつかの影響を与えます。
eval に依存する代わりに、組み込みの JSON.parse を介して JSON を解析します。 IE8 以降のブラウザはローカル JSON 操作をサポートしているため、完全に安全です。
文字列の代わりにインライン関数を使用して、setTimeout と setInterval を呼び出す方法を書き直します。例:
setTimeout("document.querySelector('a').style.display = 'none';", 10);
次のように書き換えることができます:
setTimeout(function () { document. querySelector ('a').style.display = 'none' }, 10);
実行時のインライン テンプレートの回避: 多くのテンプレート ライブラリは、テンプレートの生成を高速化するために new Function() を使用します。これは動的プログラムには最適ですが、悪意のあるテキストの場合は危険です。
レポート<script>sendMyDataToEvilDotCom();</script> サーバー側で信頼できないリソースをブロックする CSP の機能はユーザーにとっても優れていますが、サーバーに送信されるさまざまな通知を取得して、悪意のあるスクリプト インジェクションを特定して修正できることは、私たちにとっても素晴らしいことです。これを行うには、report-uri ディレクティブを使用して、JSON 形式でインターセプト レポートを特定のアドレスに送信するようにブラウザーに指示できます。 <script><br /> function doAmazingThings() {<br /> alert('YOU AM AMAZING!');<br /> }<br /></script>コンテンツ セキュリティ ポリシー: デフォルト-src 'self' ...; レポート 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": " スクリプト-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)、違反ディレクティブ、およびページのすべてのコンテンツ セキュリティ ポリシー (original-policy) に違反するリソース。
実際の使用法
CSP は現在 Chrome 16 と Firefox 4 で利用可能ですが、IE10 では限定的にサポートされる予定です。 Safari はまだサポートしていませんが、WebKit の夜間ビルドが利用できるため、Safari は次のイテレーションでサポートすることを期待しています。
一般的な使用例をいくつか見てみましょう:
実用的なケース 1: ソーシャル メディア ウィジェット
Google 1 ボタンには、https://apis.google.com のスクリプトと、plusone の https:// iframe から埋め込まれたスクリプトが含まれています.google.com。 Google 1 ボタンを使用するには、戦略にこれらのソースを含める必要があります。最も単純な戦略は script-src https://apis.google.com、frame-src https://plusone.google.com です。また、Google が提供する JS スニペットが外部 JS ファイルに保存されていることを確認する必要があります。
Facebook の「いいね!」ボタンには多くの実装ソリューションがあります。サイトの他の部分から十分に分離されているため、iframe バージョンを使用することをお勧めします。これには、frame-src https://facebook.com ディレクティブを使用する必要があります。デフォルトでは、Facebook が提供する iframe コードは相対パス //facebook.com を使用することに注意してください。必要に応じて、このコードを https://facebook.com に変更してください。
Twitter のツイート ボタンは、両方とも https://platform.twitter.com からのスクリプトとフレームに依存しています (Twitter はデフォルトで相対 URL を提供します。コピーするときに HTTPS を指定するようにコードを編集してください)。
他のプラットフォームでも同様の状況があり、同様に解決できます。 default-src を none に設定し、コンソールをチェックして、ウィジェットが適切に動作していることを確認するために必要なリソースを確認することをお勧めします。
複数のウィジェットの使用は非常に簡単です。すべての戦略ディレクティブをマージするだけで、同じディレクティブの設定を一緒に保持することを忘れないでください。上記の 3 つのウィジェットを使用する場合、戦略は次のようになります。
script-src https://apis.google.com https://platform.twitter.com; .google.com https://facebook.com https://platform.twitter.com
実際のケース 2: 防衛
銀行の Web サイトにアクセスし、必要なリソースのみがロードされていることを確認したいとします。この場合、すべてのコンテンツをブロックするデフォルトのアクセス許可 (default-src ‘none’) を設定することから始めて、ポリシーを最初から構築します。
たとえば、銀行の Web サイトは、https://cdn.mybank.net の CDN から画像、スタイル、スクリプトをロードし、XHR 経由で https://api.mybank.com/ に接続してさまざまなデータを取得する必要があります。フレームも使用する必要がありますが、フレームはサードパーティ以外のローカル ページからのものです。このウェブサイトには Flash、フォント、その他のコンテンツはありません。この場合、送信できる最も厳密な CSP ヘッダーは次のとおりです:
Content-Security-Policy:default-src 'none'; .mybank.net; img-src https://cdn.mybank.net; connect-src https://api.mybank.com 'self'
実際のケース 3: SSL のみを使用する
結婚指輪フォーラムの管理者は、すべてのリソースが安全な方法で読み込まれることを望んでいますが、実際にはあまり多くのコードを書きたくはありません。大量のサードパーティ フォーラムのインライン スクリプトやスタイルを書き直すことは、彼の能力を超えています。したがって、次のポリシーは非常に役立ちます:
Content-Security-Policy:default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'
デフォルトですが-src は https を指定します。スクリプトとスタイルは自動的に継承されません。各ディレクティブはデフォルトのリソースタイプを完全にオーバーライドします。
将来
W3C の Web アプリケーション セキュリティ ワーキング グループは、コンテンツ セキュリティ ポリシー仕様の詳細を策定中であり、バージョン 1.0 は最終改訂段階に入ろうとしており、この記事で説明されている内容に非常に近づいています。 public-webappsec@ メーリング グループではバージョン 1.1 について議論しており、ブラウザのメーカーも CSP の実装の統合と改善に熱心に取り組んでいます。
CSP 1.1 には、アートボード上に別個にリストする価値のある興味深い機能がいくつかあります。
メタ タグを介したポリシーの追加: CSP を設定する推奨方法は、非常に便利な HTTP ヘッダーを使用することですが、タグまたはスクリプトを使用して設定する方が簡単です。 、しかし今のところまだ最終決定されていません。 WebKit はメタ要素を通じて権限を設定する機能を実装したため、Chrome で次の設定を試すことができます:
実行時にスクリプトを介して戦略を追加することもできます。
DOM API: CSP の次のイテレーションでこの機能が追加される場合、JavaScript を通じてページの現在のセキュリティ ポリシーをクエリし、さまざまな状況に応じて調整できます。たとえば、eval() が利用可能な場合、コードの実装は若干異なる可能性があります。これは JS フレームワークの作成者にとって非常に便利です。また、API 仕様は現在非常に不確実であるため、ドラフト仕様のスクリプト インターフェイスの章で最新の内容を見つけることができます。
新しいディレクティブ: script-nonce: 明示的に指定されたスクリプト要素のみがインライン スクリプトを使用できる、plugin-types: これによりプラグインの種類が制限されます。form-action: フォームの送信のみが許可されます。特定のソース。
これらの将来の機能に関するディスカッションに興味がある場合は、メーリング リストのアーカイブを読むか、メーリング リストに参加してください。
この記事の翻訳元: http://www.html5rocks.com/en/tutorials/security/content-security-policy/
抜粋: Jiang Yujie のブログ