CSP の XSS 攻撃に対する効果を確認する

コンテンツ セキュリティ ポリシー(CSP)は、ページに読み込まれたすべてのコンテンツがサイト所有者によって信頼されていることを確認するのに役立ちます。CSP は、攻撃者によって挿入された安全でないスクリプトをブロックできるため、クロスサイト スクリプティング(XSS)攻撃を軽減できます。ただし、厳格さが十分でなければ、CSP は簡単に回避できます。詳しくは、厳格なコンテンツ セキュリティ ポリシー(CSP)を使用してクロスサイト スクリプティング(XSS)を軽減するをご覧ください。Lighthouse では、メイン ドキュメントに適用されている CSP を収集し、回避できる場合は CSP 評価者から問題を報告します。

Lighthouse では、適用モードで CSP が見つからないという警告が表示されます。
違反措置モードで CSP が見つからないという Lighthouse レポート警告

バイパス不可能な CSP に必要なプラクティス

CSP が回避されるようにするには、次の方法を実施してください。CSP が回避できる場合、Lighthouse は重大度「高」の警告を発行します。

CSP のターゲットは XSS

XSS をターゲットとするには、CSP に script-srcobject-srcbase-uri のディレクティブを含める必要があります。また、CSP には構文エラーがない必要があります。

script-srcobject-src はそれぞれ安全でないスクリプトと安全でないプラグインからページを保護します。または、script-srcobject-src などの多くのディレクティブの代わりに、default-src を使用して広範なポリシーを構成することもできます。

base-uri は、不正な <base> タグの挿入を防ぎます。このタグを使用すると、すべての相対 URL(スクリプトなど)が攻撃者の管理ドメインにリダイレクトされるおそれがあります。

CSP はノンスまたはハッシュを使用して許可リストのバイパスを回避する

script-src の許可リストを構成する CSP は、信頼できるドメインからのすべてのレスポンスが安全であり、スクリプトとして実行できるという前提に依存します。しかし、この前提は最新のアプリケーションには当てはまりません。JSONP インターフェースの公開や AngularJS ライブラリのコピーのホスティングといった一般的で無害なパターンにより、攻撃者は CSP の領域から抜け出せる可能性があります。

実際には、アプリケーション作成者には明らかではないかもしれませんが、XSS バグを持つ攻撃者によって script-src 許可リストの大部分が回避され、スクリプト インジェクションに対する保護がほとんど提供されません。一方、ノンスベースのアプローチとハッシュベースのアプローチではこのような問題が生じないため、より安全なポリシーを採用して維持するのが容易です。

たとえば、次のコードは、信頼できるドメインでホストされている JSONP エンドポイントを使用して、攻撃者が制御するスクリプトを挿入します。

CSP:

script-src https://trusted.example.com

HTML:

<script src="https://trusted.example.com/path/jsonp?callback=alert(document.domain)//"></script>

CSP がバイパスを回避するには、ノンスまたはハッシュを使用するスクリプトを個別に許可し、許可リストの代わりに「strict-dynamic」を使用する必要があります。

安全な CSP のためのその他の推奨事項

セキュリティと互換性を強化するために、次の方法を実装します。CSP が推奨事項のいずれも遵守していない場合、Lighthouse は重大度「中」の警告を発行します。

CSP レポートを構成する

レポート先を設定すると、障害をモニタリングするのに役立ちます。report-uri ディレクティブまたは report-to ディレクティブを使用して、報告先を設定できます。report-to は現在、すべての最新ブラウザでサポートされていないため、両方を使用するか、report-uri のみを使用することをおすすめします。

コンテンツが CSP に違反している場合、ブラウザから、構成されている宛先にレポートが送信されます。これらのレポートを処理するアプリケーションがこのリンク先で構成されていることを確認してください。

HTTP ヘッダーで CSP を定義する

CSP は、メタタグで次のように定義できます。

<meta http-equiv="Content-Security-Policy" content="script-src 'none'">

ただし、可能であれば、HTTP レスポンス ヘッダーで CSP を定義する必要があります。メタタグの前に挿入すると、CSP がバイパスされます。また、frame-ancestorssandbox、およびレポートは、メタタグ CSP でサポートされていません。

CSP に下位互換性があることを確認してください

すべてのブラウザが CSP のノンス/ハッシュをサポートしているわけではないため、ポリシーに準拠していないブラウザの代替手段として unsafe-inline を追加することをおすすめします。ブラウザでノンス/ハッシュがサポートされている場合、unsafe-inline は無視されます。

同様に、strict-dynamic は一部のブラウザではサポートされていません。ポリシーに準拠していないブラウザに対しては、代替手段として許可リストを設定することをおすすめします。strict-dynamic をサポートするブラウザでは、許可リストは無視されます。

厳格な CSP の作成方法

以下は、厳格な CSP とノンスベースのポリシーを使用する例です。

CSP:

script-src 'nonce-random123' 'strict-dynamic' 'unsafe-inline' https:;
object-src 'none';
base-uri 'none';
report-uri https://reporting.example.com;

HTML:

<script nonce="random123" src="https://trusted.example.com/trusted_script.js"></script>

random123 は、ページが読み込まれるたびにサーバーサイドで生成される base64 文字列です。最新のブラウザでは、unsafe-inlinehttps: はノンスと strict-dynamic があるため無視されます。厳格な CSP の採用について詳しくは、厳格な CSP ガイドをご覧ください。

Lighthouse と CSP Evaluator を使用して、潜在的なバイパスの有無をチェックできます。既存のページが壊れるリスクなしに新しい CSP をテストする場合は、ヘッダー名として Content-Security-Policy-Report-Only を使用し、レポート専用モードで CSP を定義します。これにより、report-toreport-uri で構成したレポート宛先に CSP 違反が送信されますが、CSP は実際に適用されません。