Open3

Content Security Policy

mocknmockn

概要

Content Security Policyとは

コンテンツセキュリティポリシー (CSP) は、クロスサイトスクリプティング (Cross-site_scripting) やデータインジェクション攻撃などのような、特定の種類の攻撃を検知し、影響を軽減するために追加できるセキュリティレイヤーです。これらの攻撃はデータの窃取からサイトの改ざん、マルウェアの拡散に至るまで、様々な目的に用いられます。

CSP を有効にするには、ウェブサーバーから Content-Security-Policy HTTP ヘッダーを返すように設定する必要があります

登場人物

CSP(Content Security Policy)に関連する主要な登場人物とその関係性について説明します。(ChatGPT)

ブラウザ(ビューワー)

  • 役割:ユーザーにウェブページのコンテンツを表示し、ユーザーインタラクションを処理します。
  • 関係性:CSPに従って、ウェブページから受信するコンテンツの種類やソースを制限します。これにより、不正なスクリプトや外部からの攻撃を防ぐ役割を果たします。

サーバー

  • 役割:ウェブページやアプリケーションのコンテンツを提供し、クライアント(ブラウザ)へのレスポンスを管理します。
  • 関係性:CSPヘッダーを通じて、ブラウザがどのリソースを受け入れるかを指定します。例えば、どのドメインからのスクリプトが実行可能か、どのタイプのコンテンツが許可されるかなどを定義します。

ユーザー

  • 役割:ウェブページやアプリケーションの最終的な利用者です。
  • 関係性:ユーザーはブラウザを通じてウェブコンテンツにアクセスし、CSPによって提供されるセキュリティの恩恵を受けます。CSPはユーザーを悪意あるコンテンツやXSS攻撃から守ります。

攻撃者

  • 役割:悪意あるスクリプトやコンテンツをウェブページに挿入しようとする非倫理的なエンティティです。
  • 関係性:CSPは攻撃者によるXSS攻撃などのセキュリティリスクを軽減するために設計されています。攻撃者が注入したコンテンツがブラウザで実行されないように、CSPは特定のソースからのスクリプトのみを許可します。

脅威

  • XSS(クロスサイトスクリプティング)攻撃を軽減し、報告することを目的としています。XSS攻撃はブラウザが信頼するサーバーからのコンテンツを悪用するものです。CSPを用いると、サーバー管理者はブラウザに実行を許可するスクリプトのソースを制限でき、不正なスクリプトの実行を防ぎます。CSP対応ブラウザは、許可されたドメインのスクリプトのみを実行し、それ以外を無視します。

  • サーバーは通信に使うプロトコルを指定することも可能です。 例えば、(セキュリティの観点からはこれが理想的ですが)すべてのコンテンツを HTTPS で取得されるようにサーバーから指定することが出来ます。

設定方法

ポリシーの設定には Content-Security-Policy HTTP ヘッダーを以下のように用います。
policy の箇所には、適用したいコンテンツセキュリティポリシーを表すディレクティブから構成される文字列が入ります。

Content-Security-Policy: policy

例)
サイト管理者がウェブアプリのユーザーに、任意のドメインからの画像読み込みを許可したい場合。ただし、音声や動画は信頼された配信元からのものだけに制限し、すべてのスクリプトは、信頼されたコードをホストする特定のサーバーのみに制限する。

Content-Security-Policy: default-src 'self'; img-src *; media-src example.org example.net; script-src userscripts.example.com
  • default-src
    • 各種フェッチディレクティブが CSP ヘッダーにない場合、ユーザーエージェントは default-src ディレクティブを適用する。
  • img-src
    • 画像やファビコンのための有効なソースを定義します。
  • media-src
    • <audio>、<video>、<track> 要素によって読み込むメディアのための有効なソースを指定する。複数設定可。
  • script-src
    • JavaScript および WebAssembly のための有効なソースを指定します。

テスト

CSP は report-only モードで動作させることが可能です。このモードの場合、ポリシーによるブロックは行われず、指定した URI へポリシー違反の内容が報告されます。

ポリシーを report-only モードで動作させるには、以下のようにポリシーを Content-Security-Policy-Report-Only HTTP ヘッダーに指定します。

Content-Security-Policy-Report-Only: policy

同じレスポンス中に Content-Security-Policy-Report-Only ヘッダーと Content-Security-Policy ヘッダーが存在した場合、どちらのポリシーも考慮されます。 Content-Security-Policy ヘッダーに指定したポリシーについてはブロックが行われ、Content-Security-Policy-Report-Only ヘッダーに指定したポリシーは報告のみが行われます。

違反報告

既定では、違反内容は報告されません。違反内容の報告機能を有効にするには report-uri ポリシーディレクティブを指定し、報告先の URI を 1 つ以上指定する必要があります。

Content-Security-Policy: default-src 'self'; report-uri http://reportcollector.example.com/collector.cgi

例)

{
  "csp-report": {
    "document-uri": "http://example.com/signup.html", // 違反が生じた文書の URI。
    "referrer": "", // 違反が生じた文書のリファラー。
    "blocked-uri": "http://example.com/css/style.css", // 読み込みがブロックされたリソースの URI。ブロックされた URI が document-uri とは異なるオリジンだった場合、ブロックされた URI はスキーム・ホスト・ポートのみを含むように切り詰められる。
    "violated-directive": "style-src cdn.example.com", // 実行により違反を起こしたディレクティブ。
    "original-policy": "default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports" // HTTP ヘッダーに元々指定されていたポリシー。
  }
}

キーワード値

  • 'none'
    • すべてのリソースの読み込みを許可しません。
  • 'self'
    • 現在のオリジンからのみリソースの読み込みを許可します。
  • 'strict-dynamic'
    • ページ内のスクリプトに付随する nonce やハッシュによって与えられた信頼は、それが読み込むスクリプトに拡張されます。
  • 'report-sample'
    • 違反したコードのサンプルを違反レポートに含めて記載することを要求する。

参考

https://developer.mozilla.org/ja/docs/Web/HTTP/CSP
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Content-Security-Policy

mocknmockn

AWS CloudFrontとセキュリティヘッダー

概要

CloudFrontのオリジンに対してセキュリティヘッダーを設定するするには以下2つの方法がある。

  • AWSマネージドポリシーを使用する。
  • CloudFront Functionsを使用する。

要件に基づいて柔軟に設定を行う必要があることが多いので、CloudFront Functionsを利用しレスポンスヘッダーにセキュリティヘッダーを追加する。

設定方法

HTMLを含む場合

以下コードをCloudFront Functionsに設定する。

function handler(event) {
    var response = event.response;
    var headers = response.headers;

    // Set HTTP security headers
    // Since JavaScript doesn't allow for hyphens in variable names, we use the dict["key"] notation 
    headers['strict-transport-security'] = { value: 'max-age= 63072000; includeSubdomains; preload'};  // 2年間。サブドメイン含む。プリロードリスト使用。
    headers['content-security-policy'] = { value: "default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'; frame-ancestors 'none'"}; 
    headers['x-content-type-options'] = { value: 'nosniff'};
    headers['x-frame-options'] = {value: 'SAMEORIGIN'};
    headers['referrer-policy'] = {value: 'strict-origin-when-cross-origin'};
    
    // Return the response to viewers 
    return response;
}

参照元にあるheaders['x-xss-protection'] = {value: '1; mode=block'};は現在非推奨のため削除した。
参照元のコードは若干古い可能性があるので、公式ドキュメントのマネージドポリシーの値を参考にした。

参考

https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/modifying-response-headers.html
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/understanding-response-headers-policies.html
https://zenn.dev/thirosue/articles/00d5a65fe9d694
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/using-managed-response-headers-policies.html
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/using-managed-response-headers-policies.html
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security#preloading_strict_transport_security
https://hstspreload.org/

mocknmockn

その他Security Header

概要

CSPの他に設定されることが多いSecurity Headerの概要を以下にまとめる。

strict-transport-security

指定した有効期間内はブラウザ(ユーザエージェント)が同一ドメインにアクセスする際はTLSによる通信を強制する仕組み。

例)
既存および将来のすべてのサブドメインで、1 年間を期限として HTTPS を使用する設定です。これは HTTP のみで提供できるページやサブドメインへのアクセスをブロックします。

Strict-Transport-Security: max-age=31536000; includeSubDomains

x-content-type-option

ファイルの内容をContent-Type属性から判断するよう強制する。
IEではContent-Typeを指定していても、htmlと勝手に判断してJavascriptが実行されてしまうことがあるためMSが実装した。他ブラウザ向けにも設定されることが多い。
コンテンツスニッフィング:ブラウザがMIMEタイプを推測すること。

例)
リクエスト先のタイプが style でありその MIME タイプが text/css ではない場合、または、タイプが script で MIME タイプが JavaScript の MIME タイプではない場合にリクエストをブロックします。

X-Content-Type-Options: nosniff

x-frame-options

X-Frame-Options は HTTP のレスポンスヘッダーで、ブラウザーがページを <frame>、<iframe>、<embed>、<object> の中に表示することを許可するかどうかを示すために使用します。サイトはコンテンツが他のサイトに埋め込まれないよう保証することで、クリックジャッキング攻撃を防ぐために使用することができます。
クリックジャッキング:悪意のある埋め込まれた外部サイトページ上のボタンをクリックすると、利用者に意図しない操作を実施させるといった行為。

例)

X-Frame-Options: DENY // 自サイト、他サイトどちらも読み込み不可
X-Frame-Options: SAMEORIGIN // 同じオリジンのサイトであれば読み込み可能

※ALLOW-FROM uriは廃止。

referrer-policy

(Referer ヘッダーで送られる) リファラー情報をリクエストにどれだけ含めるかを制御するHTTPヘッダー。
HTML でこのポリシーを設定することもできます。

例)

Referrer-Policy: strict-origin-when-cross-origin // (デフォルト)同一オリジンのリクエストを行う際は全てのURL、クロスオリジンではプロトコルのセキュリティ水準が同じ場合のみオリジンを送信し、低い場合はRefererを送信しない。
Referrer-Policy: no-referrer // 送信されるリクエストからRefererが省略される。
Referrer-Policy: no-referrer-when-downgrade // プロトコルが同一以上のセキュリティ水準の場合のみRefererを送信する。
Referrer-Policy: origin // オリジンのみが Refererで送信される。

一般的にはstrict-origin-when-cross-originを設定するのが推奨される。

x-xss-protection

ブラウザの「XSS フィルタ」を有効にするためのHTTPヘッダー。
反射型クロスサイトスクリプティング攻撃を検出したときに、ページの読み込みを停止する。
現在は非推奨。

例)

X-XSS-Protection: 0 // XSS フィルタリングを無効化する。
X-XSS-Protection: 1 // XSS フィルタリングを有効化(通常はブラウザーの既定値)する。クロスサイトスクリプティング攻撃を検知すると、ブラウザーはページをサニタイズする(安全でない部分を取り除く)。
X-XSS-Protection: 1; mode=block // XSS フィルタリングを有効化する。攻撃を検知すると、ページをサニタイジングするのではなく、ページのレンダリングを停止する。

注意事項(重要)

サイトが強力な Content-Security-Policy を実装しており、インライン JavaScript ('unsafe-inline') の使用を無効にしている場合、これらの保護は現代のブラウザーではほとんど不要となります。

逆に、最新バージョンのブラウザではx-xss-protectionに対応しておらず、x-xss-protectionを設定することでスクリプト実行を許してしまう脆弱性の原因となる可能性もあるため基本的には使用しないのが良い。

参考

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Strict-Transport-Security
https://qiita.com/rocinante-ein/items/8250ec6a6712a9dcb96a
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Content-Type-Options
https://qiita.com/kohekohe1221/items/f87a9308b606172b5f15
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Frame-Options
https://qiita.com/gotchane/items/4d31b01381f47100de7f
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Referrer-Policy
https://qiita.com/c0ridrew/items/7f2c9dad12543fa2662f
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-XSS-Protection
https://qiita.com/KWS_0901/items/c7c06f2bb01e572b1850
https://www.secure-iv.co.jp/techblog/7498