Spring Securityのドキュメントを1から斜め読む 2
Part 2
セキュリティヘッダのところについて。Webアプリケーションを開発する上で必要な知識なのだが、結構フレームワーク等によってはよしなにやってくれたりしていて、あまり理解しているとは言い難い。ので一回ちゃんと読んでみる
Security Http Response Header
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#headers
- Webアプリケーションのセキュリティを向上させるためのHTTPレスポンスヘッダが大量にある
- Spring Securityでは明示的にサポートしているレスポンスヘッダがある
- Spring Securityでは必要ならばカスタムヘッダによって独自のヘッダを設定できる
Default Security Headers
- デフォルトで提供しているHTTPレスポンスヘッダは以下
- Cache Control
- Content Type Options
- HTTP Strict Transport Security
- X-Frame-Options
- X-XSS-Protection
Cache-Control: no-cache, no-store, max-age=0, must-revalidate Pragma: no-cache Expires: 0 X-Content-Type-Options: nosniff Strict-Transport-Security: max-age=31536000 ; includeSubDomains X-Frame-Options: DENY X-XSS-Protection: 1; mode=block
- もしデフォルトで付与されるヘッダで不要なものがあれば、修正、削除が容易であり、これらのデフォルトに加えて追加することもできる
- それぞれのヘッダの追加詳細の説明については以下のSectionを参照の上
Cache-Control
Servletとwebfluxベースのアプリケーションでそれぞれカスタマイズする方法が違うので、それぞれのセクション見てね
- Spring Securityはデフォルトではユーザーコンテンツの保護のため、Cache機能を無効にしている
- ユーザーが認証して気密情報を閲覧した後にログアウトした場合、わたしたちは悪意あるユーザーがバックボタンをクリックするだけで機密情報を閲覧できるようにしたいわけではない
- Cache Controlヘッダは以下のように送信される
Cache-Control: no-cache, no-store, max-age=0, must-revalidate Pragma: no-cache Expires: 0
- デフォルトでは安全にするために、Spring Security はデフォルトでこれらのヘッダを付与する
- しかし、もしあなたのアプリケーションが独自の Cache Control ヘッダを提供する場合、Spring Security は手を引くことができる
- このヘッダはCSS, JSなどのような静的リソースがCacheすることができることを確保する
Content Type Options
Servletとwebfluxベースのアプリケーションでそれぞれカスタマイズする方法が違うので、それぞれのセクション見てね
- 歴史的にブラウザーは(IEを含む)はリクエストのコンテンツスニッフィングを利用してコンテンツタイプを推測しようとしてきた
- これによりブラウザは、特定のコンテントタイプが指定されていないリソースのコンテントタイプを推測してUXを向上させようとしてきた
- 例えば、ブラウザが特定のコンテントタイプを指定しないJavaScriptファイルに遭遇した時、コンテントタイプを推測して実行する
コンテンツをアップロードを許可するときにはより多くの事柄を追加する必要がある - ドキュメントを特定のドメインのみで表示する - Content−Typeヘッダをセットする - ドキュメントをサニタイズする これらの対策は Spring Security の提供範囲外である。またコンテンツスニッフィングを無効にする場合、正しく動作させるために特定のコンテントタイプを指定しないとならないことは重要なポイントである
- コンテントスニッフィングの問題は悪意あるユーザーがいくつかの脆弱性を使ってXSS攻撃ができてしまう
- 例えばいくつかのContentTypeが有効なファイル
- 例えば、いくつかのサイトが正常な POSTSCRIPT ドキュメントを Submitして閲覧することができるものがあるとする。悪意あるユーザーは、正しいJavaScriptファイルとして動作する Postscriptドキュメントを作成し、これを使って XSS 攻撃を行うことができる
- Spring Securityはコンテントスニッフィングを無効にしたデフォルトのHTTPレスポンスのヘッダ情報は以下のようになる
X-Content-Type-Options: nosniff
HTTP Strict Transport Security (HSTS)
- もし銀行のウェブサイトのURLをタイプする際に
mybank.example.com
と打つか?それともhttps://mybank.example.com
とタイプするか? - もし
https
プロトコルを省くと Man in the Middle attackを受ける可能性がある - たとえ、ウェブサイトが
https://mybank.example.com
へリダイレクトしていたとしても、悪意あるユーザーは初回のHTTPリクエストをインターセプトしてレスポンスを操作する(例えば、https://mibank.example.com
(mybankと一文字違い) にリダイレクトして Credentials 情報を盗むなど) - 多くのユーザーが https プロトコルを省略している。そのためHSTSが生まれた理由である
- HSTSホストに
mybank.example.com
が追加されると、ブラウザはmybank.example.com
へのリクエストは全てhttps://mybank.example.com
と翻訳すべきということを知ることができる - これにより中間者攻撃を大幅に制限することができる
- サイトが HSTSホストとしてマークされるための一つの方法はブラウザによって事前にホストが読み込まれることである
- 他にもう一つ
Strict-Transport-Security
ヘッダをレスポンスに付与することである- 例えば、Spring Securityのデフォルトの動作は、以下のヘッダを追加することで、ブラウザにドメインを1年間HSTSホストとして扱うように指示している(1年間はおよそ31536000秒である)
Strict-Transport-Security: max-age=31536000 ; includeSubDomains ; preload
includeSubDomains
はオプションであり、サブドメイン(例えばsecure.mybank.example.com
) を同じように HSTSドメインとして扱うようブラウザに指示するpreload
はオプションであり、HSTSドメインとして事前に読み込んでおくことをブラウザに指示する。HSTS preloadについて知りたい場合は、こちらを参照する https://hstspreload.org
HTTP Public Key Pinning (HPKP)
- HTTP Public Key Pinning(HPKP) は偽造された証明書を使った中間者攻撃を防ぐために、特定のWebサーバーで使用する公開鍵をWebクライアントに指定する
- HPKPを正しく使用することで、HPKPは怪しい証明書に対する防御を追加できる
- しかし、HPKPは複雑なため、多くの専門家は仕様を推奨していない。Chromeはサポートを削除さえしている
- HPKPが推奨されなくなった理由の詳細について知りたければ以下を参照の上
X-Frame-Options
- Webサイトにフレームを追加することを許可するとセキュリティ上の問題を発生させる可能性がある
- 例えば、巧妙なCSSスタイリングはユーザーを巧妙に意図しない箇所をクリックさせる可能性がある
- ユーザーが銀行サイトへログインしているユーザーが他のユーザーにアクセスを許可するボタンをクリックするかもしれない。この攻撃はクリックジャッキングとして知られている
クリックジャッキングに対する近代的なアプローチのもう一つは Contents Security Policyを利用することだ
- クリックジャッキング攻撃を緩和するためのいくつかの方法を提示する
- 古いブラウザをクリックジャッキング攻撃から守るためには frame breaking code を利用することができる
- ベストではないがベターな解法である
- クリックジャッキングに対処するためのより近代的なアプローチは X-Frame-Options ヘッダを使用する
- Spring Security のデフォルトでは以下のようなヘッダを使って iframe 内のページのレンダリングを無効
X-Frame-Options: DENY
X-XSS-Protection
- 一部のブラウザでは反映されたXSS攻撃をフィルタリングして排除する機能が組み込まれている
- 基本的にフィルタは有効になっていて、ヘッダを追加することで通常は有効になっていることを確認し、XSS攻撃が検出されたときに何をすべきかをブラウザに指示する
X-XSS-Protection: 1; mode=block
CSP
- CSPはWebアプリケーションがコンテンツインジェクションの脆弱性を緩和するためのメカニズム
- 例えばcross site scripting(XSS) 等である
- CSPはWebアプリケーションの作者がWebアプリケーションがリソースをロードすることを期待しているソースを宣言し、最終的にクライアント(ユーザーエージェント)に通知するための機能を提供する宣言的なポリシーである
- CSPはすべてのコンテンツインジェクションを解決するためのものではない
- その代わり、CSPはコンテンツインジェクションによる被害を軽減する助けることができる
- 最初の防御策としてWebアプリケーションの作者は入力を検証し、出力をEncodeすべきである
- WebアプリケーションはCSPを利用するために以下のような HTTP ヘッダをレスポンスに含める必要がある
Content-Security-Policy
Content-Security-Policy-Report-Only
- それぞれのヘッダはクライアントにセキュリティポリシーを届けるためのメカニズムとして使用される
- セキュリティポリシーは Security Policy Directive のセットを含んでおり、それぞれが特定のリソース表現の制限を宣言する責任を負う
- 例えば、Webアプリケーションは、以下のヘッダをレスポンスに付与することで、特定の信頼されたソースからスクリプトを読み込むことを期待するのを宣言できる
Content-Security-Policy: script-src https://trustedscripts.example.com
script-src
ディレクティブで宣言されているものとは別のソースを読もうとすると、User-agentによってブロックされる加えて、セキュリティポリシーで
report-uri
ディレクティブが宣言されている場合、違反はUser-agentによって宣言されたURLに報告される例えばWebアプリケーションがセキュリティポリシーの宣言に違反した場合、続くレスポンスヘッダはポリシーの
report-uri
ディレクティブに記載された特定のURLに対し User-agent に違反レポートを送信するように指示する
Content-Security-Policy: script-src https://trustedscripts.example.com; report-uri /csp-report-endpoint/
- 違反レポートは Web アプリケーション独自のAPIまたは Public にホストされた違反レポートサービスによって取得できるJSON構造の情報である。例えば https://report-uri.io/ など
Content-Security-Policy-Report-Only
ヘッダはWebアプリケーション作者と管理者にセキュリティポリシーを矯正するのではなく監視する機能を提供する- このヘッダは通常、サイトのセキュリティポリシーの実験や開発を行う際に使用される
- ポリシーが有効であると判断された場合、代わりに
Content-Security-Policy
ヘッダフィールドを使用することでポリシーを施行できる - 以下のヘッダを指定すると、ポリシーはスクリプトの2つの可能性のあるソースのうち1つからロードすることを宣言する
Content-Security-Policy-Report-Only: script-src 'self' https://trustedscripts.example.com; report-uri /csp-report-endpoint/
- もしこのポリシーにサイトが違反した場合、
evil.com
からスクリプトをロードしようとした場合、User-agent は違反レポートを宣言したURLへ送信する。しかし、違反リソースのロードは許可してしまう - Webアプリケーションに Content Security Policy を適用することは寒暖ではない
- 以下のリソースでサイトのSecurity Policyを効果的に開発するための支援となるかもしれない
感想
見たことがあるものもあれば知らないヘッダもあった。実際攻撃の仕方や、どんな攻撃に対して防御しているのかを知らずになんとなくつけていると何も知らないのと同等なので、ちゃんと一度頭を通しておくのは良さそう。
Recommend しないレスポンスヘッダについては広くサポートのためにあるけど、今だとあんまり採用されないのかな、くらいで理解した。
つぎは、PolicyまわりとHTTPまわり