2012-02-05

Sessionless Authentication

※ 注意!!
この記事は半分厨二病的に自作セッション機構について考えたものです。
「体系的に学ぶ 安全なWebアプリケーションの作り方」(徳丸本)などなど、
自作のセッション管理機構は脆弱性の巣窟になるのでダメ絶対!!と言われています。
https://twitter.com/#!/ockeghem/status/62883095996661760
しかし、大規模Webアプリケーションでは必要になる気がしますし、
この手の情報がWeb上でパッと見つけられなかったので、
有害な記事になる可能性があることを承知しつつ公開しています。
議論、レビューの叩き台になれば良いという意図です。



RESTful なWebサービスは本当に作れるのか考えていました。
セッションがあるとスケールアウトできない気がして。(本当にできない?)

セッションレスが難しい。
セッションレスで認証と認可をどう実現すればよいのか。
セッションレスは正確に言うと、サーバ側でセッションオブジェクトを持たない、ということ。

でも認証情報(IdやisLogon)はどこかが持つ必要があるもの。
これをクライアント側(つまりはCookie)に持たせられるのか?

ちなみにサーバ側にキャッシュサーバを置けばスケールアウトするんじゃね?
という気もしたのですが、まあそれは置いておきます。


まず、普通にCookieにIDやisLogonのvalueを持たせてみます。
ダメです。
書き換えれば他人になれますし、好きにログインできます。

ということで、暗号化かハッシュ化でなんとかできないか考えます。
問題は、key や salt をどうするかです。
なぜなら、例えばkeyがみんな共通だった場合、そのkeyを知る人で悪い人がいたら終了です。
期間で区切って定期的にkey変更すれば大丈夫そうでもありますが、
1人にやぶられると何でもされるのが残念です。

ということで、key か salt を分けます。
salt とします。
ユーザごとに、ID や isLogon など、書き換えられると困る類の属性に対する salt を生成して永続化しておきます。
そしてクライアントに送るCookieは、属性値に、対応するsaltを付けた上でハッシュ化した値とします。
これで、もし誰かが自分のある属性値に対応するsaltを特定できたとしても、
他の属性値を書き換えることや、他人の値になることはできません。

でも実はこれでは、Cookie値そのものを記憶してしまえばログインできます。
結局いつもCookieの中身が同じだからです。
1回ログインして、そのときのIDとisLogonのCookie値を覚えておけば、
次回以降はログイン機能をバイパスしてログインするということもできます。
で、これだけだと必要なものがパスワードからCookie値に変わっただけで、
どのみちCookie値も基本的に本人しか知らないからあまり問題ないです。

しかしCookieが漏れた場合(XSS脆弱性があった場合など)ダメです。
この場合を含め、ログオフ機能のためにも、saltを変更する機能が必要です。


さらに例えば、何らかの所有権限の変更などがあった場合に問題があります。
もう今だとその値を取りえない、という値にしてしまうことが可能だからです。

というわけで対策したいです。
根本的対策1:権限情報の変更などの場合に、salt を変更する
保険的対策1:アプリケーション共通の salt を定期的に生成、変更する
Cookie値 = hash(isLogon, isLogonSalt, appSalt)
という関数にします。



以上、ぼくのかんがえたさいきょうのせっしょんでした。
(まじめな話、叩いたらオープンソースしたい)


※最後に再度注意!!
「自作のセッション管理機構は脆弱性の巣窟になるのでダメ絶対!!」
https://twitter.com/#!/ockeghem/status/62883095996661760