こんにちは、GMO NIKKOのryoutakoです。普段はRuby on Railsを使った開発やプロダクトの脆弱性診断などセキュリティ関連の業務をしています。
今回はHTTPヘッダーの一つであるContent Security Policy(以降CSPヘッダー)について書いていきたいと思います。
経緯
最近の業務でCSPヘッダーに関連する業務を行う機会があったのですが、正直CSPヘッダーのことはぼんやりとしか理解できていない状態でした。なので着手するにあたってCSPヘッダーの知識を復習したので、今回はその内容を共有しようと思います。
CSPヘッダーとは
CSPヘッダーはウェブサーバーがブラウザに送信するHTTPヘッダーの一種で、コンテンツセキュリティポリシーを定義します。このポリシーは特定のリソースの読み込みや実行を制御し、ウェブページ上での潜在的なセキュリティリスクを軽減します。
また、CSPヘッダーはXSS攻撃に対する有効な対策の1つになります。CSPヘッダーを使用するとブラウザは許可されたソースからのみスクリプトを実行するため、悪意のあるスクリプトの埋め込みを防ぐことができます。しかしながらCSPヘッダーだけでXSSを対策することは難しいため、他のセキュリティ対策と併用して実施するプラスアルファの対策と認識しておくのが良いと思われます。
CSPヘッダーで使用できるディレクティブ
default-src
: デフォルトのリソース読み込み元を定義します。script-src
: JavaScriptファイルの読み込み元を指定します。style-src
: CSSファイルの読み込み元を指定します。img-src
: 画像の読み込み元を指定します。font-src
: フォントファイルの読み込み元を指定します。frame-src
: フレームやiframeの読み込み元を指定します。- etc
CSPヘッダーの使用例
今回はローカル環境に検証用のサイトを用意してみました。XのようなSNSをイメージして作成(当社比)しており、検証用に意図的に蓄積型XSSの脆弱性を追加してあります。
つぶやきの中にXSSのトリガーとなるJavaScriptを仕込むことで、「XSSのつぶやき」が一覧に表示されたユーザすべてで任意のスクリプトが実行されるといった具合です。
ここで以下のようなmetaタグでCSPヘッダーを設定して再度検証します。
1 |
<meta http-equiv="Content-Security-Policy" content="script-src 'none';"> |
「script-src 'none'
」で全てのJavaScriptの実行を禁止したのでXSSが発動しませんでした。このようにサイト内でのJavaScriptや、その他のソースの利用を制限することで外部からの攻撃に対して防御することができます。
CSPヘッダーの使用例(実践編)
とはいえ上記のように全てのJavaScriptを制限することはほとんどないので、より実践に近い形でのCSPヘッダーの使用例を挙げてみたいと思います。
※紹介するCSPヘッダーの設定内容はあくまで例になります。設定内容はサービスの内容により変わるので、参考までにお願いします。
例1: 銀行や金融機関のウェブサイト
想定する機能: 口座残高確認、取引履歴閲覧、送金など
要件: セキュリティリスクの最小化、信頼性の観点から外部のリソースやスクリプトの使用を極力避けたい。
CSP設定:
1 |
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; connect-src 'self'; frame-ancestors 'self'; upgrade-insecure-requests;"> |
設定の理由:
・この設定では全てのコンテンツ(JavaScript、CSS、iframe提供元など)が同一オリジンからのみ許可されます。これにより、不正なスクリプトの注入やクロスサイトスクリプティング攻撃を防ぐことができます。
・connect-src 'self';
でページ内のリクエストの送信元を制限します。これにより不正な外部への通信が防止されます。
・frame-ancestors 'self';
で同一オリジンのフレームからのみ埋め込みを許可します。これにより、クリックジャッキングなどの攻撃から保護されます。
・upgrade-insecure-requests;
でページ内のHTTPリンクを自動的にHTTPSに変更します。これにより中間者攻撃やデータの盗難を防止し、通信の安全性を向上させます。
例2: ユーザが短文のつぶやきや投稿を共有するSNS
想定する機能: テキストや画像の投稿、それらの共有、投稿に反応したりコメントを残すなど
要件: 最低限のセキュリティを確保しつつ、ユーザが投稿した内容やコメントを動的に表示したり、投稿内容を装飾できるようにしたい。また、パフォーマンスの観点から画像は専用の外部サーバからホスティングしたい。
CSP設定:
1 |
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'https://image.example.com' data:; connect-src 'self'; frame-ancestors 'self'; upgrade-insecure-requests;"> |
設定の理由:
・JavaScriptとCSSを同一オリジンまたはインラインで許可することにより、特定の要素に対する動的な操作やスタイルの適用が可能になります。
・img-src 'https://image.example.com'
で専用の外部サーバからのみ読み込みを許可します。
・connect-src
、frame-ancestors
、upgrade-insecure-requests
の設定に関しては例1と同様。
さいごに
今回はCSPヘッダーについて書いていきましたが、CSPヘッダーはWebアプリケーションのセキュリティを強化するために重要な役割を果たすためこの機会に理解を深められてよかったです。また、CSPヘッダーに限らず他のセキュリティヘッダーについても学ぶことで、防御手段や攻撃方法の理解も深まることを実感できたので、今後も機会があれば取り組んでいきたいと思います。
ここまで読んでいただきありがとうございました!!
Ruby on Railsを使った開発、プロダクトの脆弱性診断などをやってます
オレンジ色と犬と猫と食べることと歌うこととピアノが好きです。