認証・認可の脆弱性:ログインとIDOR
多要素認証の抜け道
この回でやること
パスワードとコードは正しく確かめているのに、2段階目を飛ばして入れてしまう。多要素認証(MFA)の流れの実装に空く穴と、その直し方を対で扱います。
- 読む 約 7 分
- 最後にクイズ 1 問
このレッスンで学ぶこと
多要素認証(MFA)の抜け道は、パスワードとコードの検証そのものではなく、その前後をつなぐ流れの実装に空きます。この回はその穴を直し方と対にして扱い、確かめるのは練習用のショップだけにします。
読み終えると、コードを入れずに目的のページへ行けないかを、自分の手で確かめられるようになります。
1段階目の通過でセッションを配ってしまう
MFAは2段階です。まずパスワード、次に6桁のコード。素直に作ると、1段階目のパスワードが合った時点で本物のセッションを配り、コードの画面はそのあとに見せるだけ、という形になりがちです。
プレーンテキスト
POST /login name=tanaka password=正しいパスワード
→ session を発行して Cookie で返す ← ここが穴
→ 画面はコード入力へ移動するこのとき、コードを入れずに自分のページへ直接アクセスすると、もう配られたセッションで通ってしまいます。2段階目は見た目の上に乗っているだけで、認可には効いていません。
直し方は、1段階目では本物のセッションを配らないことです。パスワードが合った段階では「コード待ち」を表す一時のトークンだけを渡し、コードが合ってはじめて本物のセッションに切り替えます。そのうえで各画面が、MFAを通過済みかどうかを毎回サーバ側で確かめます。
コードの検証に回数制限が無い
6桁のコードは100万通りです。多く見えますが、1回のログインの間に何千回も送れるなら、当たるまで試されます。総当たりの回で見た「数える」仕組みは、このコードにも要ります。コードの検証にも失敗の回数を数え、上限で打ち切り、コードは短時間で切り替えます。
コードが他人のものでも通る
もう1つ、コードの持ち主を確かめていない穴があります。tanakaでパスワードを通し、コード入力の画面で、攻撃者が自分あてに受け取った別アカウントのコードを送ったら通った、という形です。サーバがコードとログイン中の利用者を紐付けず「有効なコードか」だけを見ていると起きます。コードは必ず、1段階目を通った本人に発行したものかを突き合わせます。
偽サイトでコードを中継される
これらを塞いでも、利用者を偽サイトに誘い込む手は残ります。本物そっくりの画面でパスワードとコードを入力させ、攻撃者がそれを即座に本物へ中継すると、正しいコードが本物に届いてしまいます。コード自体は正しいので、サーバ側からは見分けがつきません。
2段階目を「画面を1枚増やす」で実装すると、URLを直接叩かれた瞬間に無くなります。効くのは画面の順番ではなく、コードが合うまで本物のセッションを配らないことと、各画面がMFAの完了をサーバ側で確かめることです。
前回見たとおり、この中継まで止められるのは、接続先のドメインを鍵の側で確かめる物理的な鍵です。SMSやアプリのコードは、人が読んで打ち込む以上、中継できます。何を防ぎたいかで手段を選ぶという前回の話が、ここで具体的な設計に効いてきます。