http://b.hatena.ne.jp/entry/s/co3k.org/blog/why-do-you-use-jwt-for-session
と厳しい叱責を受けたため、無能の見識を書いてみた。
「聞くは一時の恥、聞かぬは一生の恥」のとおり、
せっかくの機会のため、びしばしセキュリティに関する認識の甘さを指摘してほしい所存
作ったシステムではexpは約1時間でやってしまいました(機密保持契約違反を恐れ多少ぼかしております)
確認している間に1時間はかかるからいいやと思ってしまっていた
師はきっとJWT生成直後3秒でユーザーが
と気づいて通報
そして師が2秒で
「これは、セッションハイジャックだ!」
と検知してセッション遮断、秒速で一億円の被害が出るところを阻止する前提なのではないかと推測している
これは確かにJWTだと厳しそうだ
セッションを任意に切れることに意味はないのでは、と思えてきたが、浅はかだろうか
(師はログインを即座に検知してセッションを切れるから問題ないのか)
とにかくアカウントロック機能を作れば上記の懸念全てにきれいに対応できそうに見えている
この理屈だと例えば.envに書くような他のkeyも定期的な交換が必要に見える
これはまずい、自分の今までの見識の甘さを思い知らされた
keyは初回に設定したのみで、定期的な交換を勧める文が見つからない
私の検索力不足なのかと思ったが、もしかして彼らもこの危険性に気付いていないのではないか
JWTはhash化してつないでいる前提で
解読時間は下記を参考に、計算はwindows10の電卓アプリを用いて手動で行った
https://ja.wikipedia.org/wiki/%E7%B7%8F%E5%BD%93%E3%81%9F%E3%82%8A%E6%94%BB%E6%92%83
英数字大文字小文字で約60の時は10桁で20万年と書いているが
現代の解析技術は20万倍は速度が出ると仮定して1年として計算する
日本語に直すと60京4661兆7600億年かかる計算となった
実際にはこれが6.0466176e+17倍されさらに3600倍されつまりどういうことだ
そもそも師は何年で交換したら安全と書いていないが、何年なら安全という意見だったのだろうか
私の理解ではとかくuser_idのみ必要なら意味がないと思っていたため落ち込んでいる
まず、IDとpassを内蔵するネイティブアプリに対するapiサーバでの実装経験しかないこと
JWTが切れたら都度IDとpassを投げる方向でリフレッシュトークンは実装しなかったことを告白しておく
そのためapiサーバで上記前提で用いた場合に考えたことを書く
webアプリのJWT実装経験はないので、そちらの論は差し控えさせていただく
では危険で
JWT送信→セッション(cookie形式?)送信切り替え→セッションからuser_id取得
とりあえず思いついたのは下記だった
tokenはheaderにbearerで付けユーザーID(あるいはそれに代わる特定可能な識別子)が含まれる
httpsで通信するのでパケットキャプチャによる傍受は不可能と思っていた
(httpで通信するのはJWTとかcookieとか関係なく傍受できるため考慮しない)
0に何をかけても0なので、何回送っても解読されないならJWTを何回送っても問題ない
というかJWTが抜けるなら同様にheaderに付けるcookieでも抜けると思うので
JWTだからといって危険性に差はない、という論拠により安全性は変わらないという個人的結論になった
※余談だが、たまに送る回数が少ない方が安全という
攻撃者がアプリに保存されたJWTが取得できるならIDもpassも同じ方法で抜けそうに見えた
(厳密には保存場所が違ったかもしれんが実装依存なので同一とする)
その前提のため、わざわざ
JWT送信→セッション(cookie形式?)送信→セッションからuser_id取得
で接続しても、おそらくcookie形式で送れる何かもJWTらと同じ方法で抜かれると思われる
つまりcookieだろうがJWTだろうがアプリから直接情報が抜かれる危険性には変わりがないという結論になった
つまりcookieだろうがjwtだろうがidとpasswordの組だろうが同じ危険性で抜かれる可能性があり、いずれでも同じことができるなら
JWT→user_id
でいいじゃん、わざわざcookieと同様の形式を間に挟むの無駄じゃん、となりコメントの発言に至った
ここまで書いて、常にJWTにsession_idを含めておいて送ることを意図されていた可能性にも気づいたが
セッションにするメリットとして唯一思いついているのは任意にサーバ側でセッションを切れることだが
それを指していたのであろうか
余談だが、ブコメの雰囲気に日和って「ユーザーIDのみ入れ」(そもそもJWTを自然に作れば入るのだが)
というセッションストア的にJWTに他の情報を入れると入れない時に比べて危険性があがることに同意したような記載をしてしまったが
結局JWTが奪えたら中身に関係なくbearerとしてセットして接続するだけなので
正直JWTを使った時点でついでにセッションストアのように使おうが使わまいがセキュリティ的にそこまで変わらないのでは、と思っている
強いて上げるならセッションに保存している内容が分かる可能性があり、サーバー内部の実装が推測できる危険があるくらいだろうか
でも暗号化したらよいのでは、と思った
expを適切に設定しつつ、必要ならアカウントロック機能を入れる
(アカウントロック機能はJWTに関係なく被害の増加を抑えられる可能性がある)
少なくともapiサーバ→ネイティブアプリに関して、セッションIDを含めても危険性は変わらない
正直webアプリでも大して変わらんのでは、と思っているのは内緒である