認証・認可の脆弱性:ログインとIDOR
認可はサーバー側で判定する
この回でやること
画面を隠すのは表示の話にすぎないこと、判定を1か所に寄せること、既定は拒否にすることという、この章の締めの設計論を扱います。個別の攻撃ではなく、崩れない土台の作り方です。
- 読む 約 7 分
- 最後にクイズ 1 問
このレッスンで学ぶこと
認可の土台は、個別の攻撃を1つずつ塞ぐ話とは別に、崩れが起きにくい形をあらかじめ作っておくことです。この回はここまでの崩れ方を振り返って、その土台を3つの柱にまとめます。
読み終えると、新しいエンドポイントを足したときに穴が開くかどうかを、土台の形から予測できるようになります。
画面を隠すのは、認可ではない
垂直の回で見たように、メニューからリンクを消しても、その先のエンドポイントが判定しなければURLを直接叩いて通ります。ボタンを消す、項目を出し分ける、入力欄を無効にするといった操作は、すべて画面の表示の話です。攻撃者は画面を使わず、リクエストを直接組み立てて送ります。認可の判定は、画面ではなく、リクエストを受けるサーバー側にしか置けません。画面の出し分けは使い勝手のためにやってよいのですが、それを守りだと数えないでください。
判定を1か所に寄せる
BOLAとテナントの回で見た塞ぎ漏らしは、同じ判定が口ごとに散らばっていて、どこかで書き忘れることから起きました。だから、認可の判定はエンドポイントごとにばらばらに書くのではなく、資源に触れる前に必ず通る共通の場所に寄せます。
プレーンテキスト
リクエスト
→ 共通の関門で「この主体はこの資源にこの操作をしてよいか」を判定
→ 通ったものだけが、資源を扱う処理に進む判定が1か所にあれば、直すときもそこだけを直せます。口ごとに散らばっていると、1つ直しても隣が漏れます。
既定は拒否にする
3つ目の柱は、判定の初期値を拒否にすることです。禁止したいものを一覧にして拒む作りは、一覧に載せ忘れたものが通ってしまい、既定が許可になります。逆に、許可するものだけを明示し、それ以外は自動的に拒否する作りにすると、新しいエンドポイントを足したときも、許可を書くまでは閉じたままです。
ログイン済みであることは、次の1件を触ってよい理由にはなりません。認証はサーバー側で確かめた主体を1つ決めるところまでで、その主体がこの資源にこの操作をしてよいかは、そこから別に判定します。既定を拒否にしておくと、この判定を書き忘れた口が自動的に閉じます。
手を動かす
練習用の環境で、直したエンドポイントに対し、他人の資源を要求したときの応答を確かめてください。拒否は、存在しない資源を要求したときと同じ応答にします。「あなたのものではありません」と返すと、その資源が実在することを教えてしまうためです。