02.Spring Securityとは(できること)
概要
この記事では、Spring Securityとは何か?を書いていきたいと思います。
名前からしてセキュリティ対策をするためのものということは予想がつくと思います。
実際その通りなのですが、「セキュリティ対策」の機能で重要なことがあると思っています。
「何を守ってくれるのか?」
これです。
これを正確に把握しておくことが重要です。
そして次に、これが重要かと思います。
「守る必要があるのか?」
予算と開発期間が限られる中で、世の中に知られた対策を全てすることは不可能なので、システムの性質ごとに必要な対策を
取捨選択していくのだと思います。
Spring Securityでも、「何を守ってくれるのか?」が重要で、それを把握することで自然に「Spring Securityとは何か?」が分かるかと思います。
【補足】
記事の内容はSpring Security5について記述しています。
「何を守ってくれるのか」を把握するのがなぜ重要か
冒頭である機能が「何を守ってくれるのか?」を把握するのが重要と書きましたが、なぜ重要なのでしょうか。
それは、守ってくれるものを勘違いしていると目的を達成できないからです。
少し、例を見てみます。
WEBで色々なSpring Securityの記事を読んでいて、PasswordEncoder機能の次のような記事にあたりました。
「SpringSecurityで導入されたPasswordEncoderは、メモリ上のパスワードも平文で保存されていると危険なので暗号化する目的で使用される」
※PasswordEncoderはSpringSecurityのクラスで、一方向暗号化(ハッシュ化)して元のパスワードを推測しずらくする変換器です。
問題は「メモリ上のパスワード」という部分です。
PasswordEncoderは、SpringSecurityの公式リファレンスを読むと、SQLインジェクションなどでDBのPW文字列が盗まれたケースを想定して、
PWが盗まれても悪さをしずらくするためと書かれていて、「守ってくれるもの(想定ケース)」が全然違います。
メモリ上のパスワードを守るのではなく、盗まれたパスワードを守るのです。
実際問題として、ログイン処理するときはリクエストパラメタを平文で受け取るので、メモリ上にはPWが平文で残ってしまいます。
Javaのガベージコレクションの性質上、メモリ上からすぐには消えないので、メモリを読み取れる脆弱性があれば
当然、メモリ上の平文パスワードの読み取りは防げません。
PasswordEncoderでもメモリ上の平文パスワードを削除することはできません。
つまり、PasswordEncoderはメモリ上の平文パスワード流出を防げません。
しかし、もし、メモリ上の平文パスワードの値も守らないといけない要件があって、対策の選択肢としてPasswordEncoderを選択したらどうでしょう?
意味がないですよね?
ですので、「あるセキュリティ機能が何を守ってくれるのか」を把握しておくことが重要です。
【蛇足】
ちなみに上記のメモリの値についてですが、そもそもどの言語も守るのは難しいですし、メモリを読み取れてしまう脆弱性をつかない限りは
まず、攻撃が成功しません。
ですので、メモリ上の値を守ることを考えるのは通常は時間がもったいないかなと思います。
「守る必要があるのか?」ということも冒頭で書きましたが、このケースでは確率的に低いので対策を立てる必要はないのでは?というように
そもそも対応するか?を考えるべきかと思います。
Spring Securityで守るもの
Spring Securityで提供しているのは、商業(エンタープライズ)で用意できる汎用的なセキュリティ機能だけです。
以下をお読みいただき、提供されている機能の範囲のイメージを持っていただけるとありがたいです。
認証・認可
Spring Securityでメインで提供しているのは、認証と認可です。
認証とは、ログイン時にID/PWが正しいかをチェックする機構です。
認可とは、ある権限のユーザが、ある画面やリンクを表示して良いかを判断し、表示する/表示しないを制御する、アクセス制御の機構です。
カスタマイズも簡単にできるので、かなり便利です。
<認証について>
認証方式は、設定ファイルによるID/PWの保存、DBによる保存、の他に、OpenID、LDAP、AOuth2など様々な方式が用意されています。
<認可の注意点>
認可の機能は、ロール(権限)を用意して、ロールごとに閲覧可能な画面かどうかをチェックします。
例えば、ROLE_ADMINをユーザtaroに付与して、ROLE_ADMINにA画面の閲覧許可を与えると、taroはA画面を閲覧できるようになります。
注意点としては、「ユーザ1がユーザ2の情報を閲覧できないようにする」、といった機能はないので
画面を作るときに自分で実装する必要があることです。
<(補足)ユーザ1がユーザ2の情報を閲覧できないようにする機能の実装例>
やってしまいそうな間違った実装方法としては、例えば自分のプロフィールを表示する画面の場合、前の画面からリクエストパラメタでログインIDを受け取り、
そのログインIDでDBからプロフィールの値を取得して画面を表示するということをやってしまいがちです。
しかし、それでは、リクエストパラメタを改ざんされれば他のユーザのプロフィールを画面表示してしまい、脆弱性になります。
対策としては、ログイン情報はSpringSecurityから取得できるので、ログインIDをSpringSecurityから取得し、そのログインIDで
DBからプロフィールの値を取得して画面表示するようにします。
これは一例ですが、SpringSecurityは「なりすまし」を守る思想はありませんので、このように自作対応する必要があります。
実際、「なりすまし対策」は汎用的に作れるものでもないので、こういったものには対応できないイメージを持っておいた方がよいかと思います。
HTTPレスポンスヘッダ
一般的なHTTPレスポンスのヘッダで行うセキュリティ対策の機能も持っています。
例えば一般的に、クリックジャッキングの対策として「X-Frame-Options」をHTTPレスポンスヘッダに付与することがあります。
このHTTPヘッダはApacheで付与することもできますが、SpringSecurityでも設定に記述するだけで付与できます。
他にも、このようなHTTPレスポンスのヘッダに付与するセキュリティ対策の機能をいくつか持っています。
・cache-control ・・Cache-Controlヘッダに no-cacheなどの値を設定します。
・xss-protection ・・X-XSS-Protectionをヘッダに付与します。
・hsts ・・ HTTP Strict Transport Securityをサポートします。
・frame-options ・・クリックジャッキング対策(X-Frame-Options)を付与します
・content-type-options ・・ X-Content-Type-Optionsをヘッダに付与します。値は常に'nosniff'です。
・hpkp ・・HTTP Public Key Pinningをサポートします。
・content-security-policy・・Content Security Policyをサポートします。
・referrer-policy ・・リファラーのサポートをします。no-referrerなど様々な値を設定できます。
CSRF
有名なクロスサイト リクエスト フォージェリーという攻撃に対する対策をします。
自作するとかなり工数が掛かるので、とても便利です。
詳しくは、次のページに書いています。
ファイアウォール(HttpWirewall)
URLに不正がないか?などを確認する機能です。
例えば、URLにトラバーサル(/../)が含まれていないか?や、URLにダブルスラッシュ(//)が含まれていないか?をチェックして
含まれる場合はエラーにします。
その他の機能
他にも、セッション数の制御やcorsのサポートなど、いろいろな機能があります。
その他
認証を回避できる脆弱性について
認証を回避できる脆弱性(cve-2018-1199)が存在しますので、最新版を使用するようにお気を付けください。
SpringSecurity5.x系では、5.0.0が該当です。4.2系では、4.2.0 - 4.2.3が該当のようです。
簡単ですが、この記事に書いてみましたので参照ください。
最後に
存在している機能の全体の印象としては、商業で使用するような汎用的な機能です。
ですので、「SpringSecurityを導入しているからセキュリティ対策は考えなくてよい」と考えるのではなく、
1つ1つ、対策機能がSpring Securityにあるかを確認することをお勧めします。
とはいえ、ここで紹介した機能は一部です。
SpringSecurityを導入することで、自作するより格段と工数が減り、メンテ性が高くなります。
Created Date: 2018/08/18