com4dc’s blog

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

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

諸事情あってSpring Securityをちゃんと理解しないとダメになってしまったので、ひとまずドキュメントを全部読むから始める。

とはいえめちゃくちゃボリュームあるので適宜スキップしつつ、適当な翻訳と自分の理解のためだけにメモっていく。翻訳に関しては一応自分で解釈しつつ翻訳しながら、確認とちょっとした間違いを直したり確認したりするために、Google翻訳とDeepLを併用している。つまりわたしの翻訳がメインなので適当である。あまり信用あるソースにはならないということだけ書いておきます(こんなの参考にする人いないと思うけど)

実際日本語のプロジェクトはあるので、ちゃんとした翻訳はこちらを参考にしたほうが良いと思う。

spring.pleiades.io

日本語になっているとどうしても読み飛ばしてしまう癖やなんとなくで進んでしまうくせがあるので、わざと自分で理解しながらやらないとちゃんと理解できない。

読んでいくドキュメント

docs.spring.io

Part.1

Preface(序文)にあたるところ。基礎的なところについて諸々記載されている。

Authentication Support

  • Spring Securityはユーザー認証をサポートしている。各スタックでサポートされている内容の詳細はServletとWebFlux の認証のセクションを参照すること
    • servletとwebfluxで大きく異なるため、セクション自体が別に設定されてる

Password Storage

https://docs.spring.io/spring-security/site/docs/current/reference/html5/#authentication-password-storage

Password History

  • 最初はPlain textで保存。なぜならアクセスするDBにもパスワードが必要だからセキュアだろと考えた
    • 悪意あるユーザーが、SQLインジェクションからのデータダンプでそのまま引っこ抜けることに気づいてオワタ
  • 一方向Hash(SHA-256とか)
    • Rainbow Tableを用いて解読され始めてオワタ
  • Salt Password
    • ハードウェアの進化によってめちゃくちゃ早く解析できるようになってしまった
  • Adaptive One-way Function。今のトレンドはこれ
    • BCrypt, PBKDF2, argon2 とか

DelegatingPasswordEncoder

  • 今やBCryptとかをデフォにしておけばよさそうだが、そうもいかない
  • 古いアプリケーションのマイグレーションを考えるとデフォルトに設定することが難しい
  • なので、Spring Securityでは DelegatingPasswordEncoder というのを用意してるのでこれを使え

Protection Against Exploits

  • 悪意ある攻撃に対しての防御について

CSRF

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

  • CSRFドメインは違うけど同じリクエストの場合、そこにCookieが乗ってしまうことによりログイン済みとされ、意図しない操作が任意で実行されてしまう可能性がある。
  • ページを返したサイトからしかリクエストを受け付けないように、ほかのドメインからのリクエストと区別して他ドメインの場合は弾く必要がある。
  • Spring Securityでは以下の二つを提供
    • Synchronized Token Pattern: ページを返す際に hidden にランダムなIDを降るのでそれが合致しないと拒否る
    • SameSite Cookie: Cookieの属性にSameSiteをつける
      • Strict: めちゃくちゃ厳しいポリシー。絶対に同じドメインじゃないとCookieを送らない
      • Lax: ちょっとゆるふわ
      • SameSiteはブラウザが対応してないとダメ。古いやつだと対応してない可能性があるので注意
  • Webブラウザを使ってユーザーが操作する場合は原則CSRFを有効にする
  • ブラウザを利用しない場合は無効にする
  • Content-Typeを明確に指定しないことで、CSRF脆弱性が生まれる可能性があるので注意

実装の考慮事項

  • ログインリクエスト、ログアウトリクエストはセッションタイムアウトとの問題で悪意あるユーザーにログイン状態を乗っ取られて機密情報を見られる可能性がある(?)
  • CSRFとセッションタイムアウト
  • Multipart (File Upload)
    • CSRFトークンを確認するためにBodyを読もうとすると、ファイルのアップロードが始まってしまう
    • つまりCSRFトークンを読もうとして、別サイトからのアップロードを許可してしまう
      • 鶏が先か卵が先か
    • 解決策は二つ
      • BodyにCSRFトークンを配置して、一時ファイルとしてアップロードを許可
        • 割と一般的
      • URLに含める
        • ただしこれはリークする可能性があるので、ヘッダとかのメタ情報に入れた方がよい
    • HiddenHttpMethodFilter
      • いくつかのアプリケーションでは、フォームパラメータを利用してHTTPメソッドをオーバーライドできる。
      • 例えば以下のフォームを利用して、HTTPメソッドを投稿ではなく削除として使える
<form action="/process"
    method="post">
    <!-- ... -->
    <input type="hidden"
        name="_method"
        value="delete"/>
</form>
  • メソッドのオーバーライドは Filter で発生する。そのFilter は SpringSecurityサポートの前に設定しなければならない。オーバーライドは post に対してのみ発生するため、実際に問題になる可能性は低い。
  • しかし、Spring Securityの Filter 前に配置するのが最も良い方法である

とりあえずここまで。次はセキュリティヘッダについて