多くのウェブ アプリケーションでは、ユーザーが制御するコンテンツを表示する必要があります。これは、ユーザーがアップロードした画像(プロフィール写真など)を提供するだけの単純なものから、ユーザーが制御する HTML をレンダリングする複雑なものまで、さまざまです(ウェブ開発チュートリアルなど)。これを安全に行うことはこれまで困難でしたが、Google は、ほとんどの種類のウェブ アプリケーションに適用できる、簡単で安全なソリューションを見つけるために取り組んできました。
信頼できないコンテンツを分離するための従来型のソリューション
ユーザーが制御するコンテンツを安全に配信するための従来の方法は、サンドボックス ドメインを使用することです。基本的な考え方は、アプリケーションのメインのドメインが example.com
の場合、信頼できないすべてのコンテンツを exampleusercontent.com
で提供できるということです。これらの 2 つのドメインはクロスサイトであるため、exampleusercontent.com
の悪質なコンテンツが example.com
に影響することはありません。
このアプローチを使用すると、画像、ダウンロード、HTML など、信頼できないあらゆる種類のコンテンツを安全に配信できます。画像やダウンロードに使用する必要がないと思われるかもしれませんが、特に以前のブラウザでは、コンテンツ スニッフィングのリスクを回避できます。
サンドボックス ドメインは業界全体で広く使用されており、長い間問題なく機能してきました。ただし、2 つの大きなデメリットがあります。
- 多くの場合、アプリケーションではコンテンツへのアクセスを 1 人のユーザーに制限する必要があります。そのためには、認証と承認を実装する必要があります。サンドボックス ドメインはメインのアプリ ドメインと Cookie を共有しないように意図的に設定されているため、安全に行うことは非常に困難です。認証をサポートするには、サイトが機能 URL を使用するか、サンドボックス ドメインに個別の認証 Cookie を設定する必要があります。この 2 つ目の方法は、多くのブラウザがクロスサイト クッキーをデフォルトで制限している現代のウェブでは特に問題になります。
- ユーザー コンテンツはメインサイトから分離されますが、他のユーザー コンテンツからは分離されません。これにより、不正なユーザー コンテンツがサンドボックス ドメイン上の他のデータを攻撃するリスクが生じます(同一生成元のデータの読み取りなど)。
また、サンドボックス ドメインではリソースが分離されたドメインに明確に分割されるため、フィッシングのリスクを軽減できます。
ユーザー コンテンツの配信のための最新ソリューション
ウェブは進化を続けており、信頼できないコンテンツをより簡単かつ安全に配信できるようになりました。さまざまなアプローチがありますが、ここでは Google で現在広く使用されている 2 つのソリューションについて説明します。
アプローチ 1: 無効なユーザー コンテンツを配信する
サイトが非アクティブなユーザー コンテンツ(画像やダウンロードなど、HTML や JavaScript 以外のコンテンツ)のみを配信する必要がある場合は、分離されたサンドボックス ドメインなしで安全に配信できるようになりました。主なステップは次の 2 つです。
Content-Type
ヘッダーは、すべてのブラウザでサポートされ、アクティブなコンテンツが含まれていないことが保証されている、よく知られた MIME タイプに常に設定します(不明な場合は、application/octet-stream
を選択するのが安全です)。- また、ブラウザでレスポンスが完全に分離されるように、以下のレスポンス ヘッダーを常に設定してください。
レスポンス ヘッダー | 目的 |
---|---|
X-Content-Type-Options: nosniff |
コンテンツ スニッフィングの防止 |
Content-Disposition: attachment; filename="download" |
レンダリングではなくダウンロードをトリガーする |
Content-Security-Policy: sandbox |
コンテンツを別のドメインで配信されているものとしてサンドボックスに入れる |
Content-Security-Policy: default-src ‘none' |
JavaScript の実行(およびサブリソースの組み込み)を無効にする |
Cross-Origin-Resource-Policy: same-site |
ページがクロスサイトに含まれないようにする |
このヘッダーの組み合わせにより、レスポンスはアプリケーションによってサブリソースとしてのみ読み込まれるか、ユーザーによってファイルとしてダウンロードされるようになります。さらに、ヘッダーは CSP サンドボックス ヘッダーと default-src
制限により、ブラウザのバグに対する複数のレイヤの保護を提供します。全体として、上記の設定では、この方法で提供されるレスポンスが、挿入や分離の脆弱性につながることはないと考えられます。
多層防御
上記のソリューションは、通常は XSS に対する十分な防御となりますが、セキュリティを強化するために適用できるハードニング対策は他にもあります。
- IE11 との互換性を確保するため、
X-Content-Security-Policy: sandbox
ヘッダーを設定します。 Content-Security-Policy: frame-ancestors 'none'
ヘッダーを設定して、エンドポイントの埋め込みをブロックします。- 分離されたサブドメインのサンドボックス ユーザー コンテンツ:
- 分離されたサブドメインでユーザー コンテンツを提供する(例: Google は
product.usercontent.google.com
などのドメインを使用)。 Cross-Origin-Opener-Policy: same-origin
とCross-Origin-Embedder-Policy: require-corp
を設定して、クロスオリジン分離を有効にします。
- 分離されたサブドメインでユーザー コンテンツを提供する(例: Google は
アプローチ 2: アクティブ ユーザーのコンテンツを配信する
アクティブ コンテンツ(HTML や SVG 画像など)を安全に配信することもできます。この場合、従来のサンドボックス ドメイン アプローチの弱点はありません。
最も簡単な方法は、Content-Security-Policy: sandbox
ヘッダーを使用して、レスポンスを分離するようにブラウザに指示することです。現在、サンドボックス ドキュメントのプロセス分離を実装しているウェブブラウザはすべてではありませんが、ブラウザのプロセスモデルの継続的な改良により、サンドボックス化されたコンテンツと埋め込みアプリケーションの分離が改善される可能性があります。SpectreJS 攻撃とレンダラ侵害攻撃が脅威モデルの範囲外である場合は、CSP サンドボックスを使用するだけで十分なソリューションになる可能性があります。
Google では、サンドボックス ドメインのコンセプトを最新のものにすることで、信頼できないアクティブ コンテンツを完全に分離できるソリューションを開発しました。主な考え方は次のとおりです。
- 公開サフィックス リストに追加される新しいサンドボックス ドメインを作成します。たとえば、PSL に
exampleusercontent.com
を追加すると、foo.exampleusercontent.com
とbar.exampleusercontent.com
がクロスサイトになり、相互に完全に分離されます。 *.exampleusercontent.com/shim
に一致する URL はすべて、静的シム ファイルに転送されます。このシムファイルには、message
イベント ハンドラをリッスンし、受信したコンテンツをレンダリングする短い HTML と JavaScript のスニペットが含まれています。- これを使用するには、プロダクトは
$RANDOM_VALUE.exampleusercontent.com/shim
に iframe またはポップアップを作成し、postMessage
を使用して信頼できないコンテンツをレンダリング用にシムに送信します。 - レンダリングされたコンテンツは Blob に変換され、サンドボックス化された iframe 内にレンダリングされます。
従来のサンドボックス ドメインのアプローチと比較して、すべてのコンテンツが 1 つのサイトに完全に分離されます。また、レンダリングするデータの取得をメイン アプリケーションが処理することで、機能の URL を使用する必要がなくなります。
まとめ
これらの 2 つのソリューションを併用することで、googleusercontent.com
などの従来のサンドボックス ドメインから、サードパーティ Cookie のブロックに対応したより安全なソリューションに移行できます。Google では、すでに多くのプロダクトを移行してこれらのソリューションを使用しており、来年にはさらに多くの移行を予定しています。