com4dc’s blog

Javaプログラマーのはずだけど運用してます

Spring Securityのドキュメントを1から斜め読む 2

Part 2

セキュリティヘッダのところについて。Webアプリケーションを開発する上で必要な知識なのだが、結構フレームワーク等によってはよしなにやってくれたりしていて、あまり理解しているとは言い難い。ので一回ちゃんと読んでみる

Security Http Response Header

https://docs.spring.io/spring-security/site/docs/current/reference/html5/#headers

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

Strict-Transport-Security は HTTPS リクエストのときだけ追加される

  • もしデフォルトで付与されるヘッダで不要なものがあれば、修正、削除が容易であり、これらのデフォルトに加えて追加することもできる
  • それぞれのヘッダの追加詳細の説明については以下の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 と翻訳すべきということを知ることができる
  • これにより中間者攻撃を大幅に制限することができる
  • RFC6797に従って、HSTSヘッダは HTTPSレスポンスにのみ注入される
  • ブラウザがヘッダを認識するためには、ブラウザははじめにSSL証明書に署名したCAを信頼しなければならない(SSL証明書だけではない)
  • サイトが 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攻撃が検出されたときに何をすべきかをブラウザに指示する
    • 例えば、フィルタはすべてをレンダリングするために最も危険性の低い方法に変更するかもしれない
    • 時にはこのようなコンテンツの変更がXSS脆弱性を新たに生む可能性がある。そのため、より良いのは修正するよりもブロックしてしまうことである
    • Spring Securityのデフォルトはこのヘッダが利用されており、コンテンツをブロックする
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/

感想

見たことがあるものもあれば知らないヘッダもあった。実際攻撃の仕方や、どんな攻撃に対して防御しているのかを知らずになんとなくつけていると何も知らないのと同等なので、ちゃんと一度頭を通しておくのは良さそう。

Recommend しないレスポンスヘッダについては広くサポートのためにあるけど、今だとあんまり採用されないのかな、くらいで理解した。

つぎは、PolicyまわりとHTTPまわり