「ちょっとだけ」が命取り?OAuth 2.0のスコープ昇格攻撃を、家の鍵で例えて解説します
こんにちは!セキュリティの世界へようこそ。今日は、Webアプリ開発では避けて通れない「OAuth 2.0」という仕組みに潜む、ちょっと怖い「スコープ昇格」という罠についてお話しします。
「OAuthって何だか難しそう…」と思うかもしれませんが、大丈夫です。まずは身近な例えから、一歩ずつ紐解いていきましょう!
—
1. OAuth 2.0を「家の鍵」で例えると?
OAuth 2.0は、一言で言えば「あなたに代わって、別のアプリに家の鍵の一部を貸す仕組み」です。
想像してみてください。あなたは友人に「家の掃除」を頼みました。でも、家全体に自由に入られるのは不安ですよね。そこであなたは、「掃除道具が置いてある物置だけ開けられる鍵」を作って渡すはずです。
この「物置だけ」という制限が、OAuthの世界では「スコープ(Scope)」と呼ばれます。
- スコープなし: 家中のどこでも入れる(恐ろしい!)
- スコープあり: 物置だけOK、リビングはNG(これが正しい姿!)
—
2. 「スコープ昇格」というズルい手口
ところが、悪い泥棒(攻撃者)はこう考えます。「物置の鍵しかもらっていないけれど、ダメ元で『リビングも開けて!』とお願いしたら、システムは許可してくれるかな?」
これが「スコープ昇格攻撃」です。
認可サーバー(鍵を作る管理人さん)が、本来のルールをチェックせずに、「あ、この人が『リビングも開けて』って言ってるから、とりあえずリビングの鍵も渡しておこう」とガバガバな対応をしてしまうと、攻撃者は本来持っていない権限を手に入れてしまいます。
これが、開発者が絶対に防がなければならない「スコープのバリデーション(妥当性検証)不足」という脆弱性です。
—
3. 実践!攻撃のメカニズムを見てみよう
開発者が認可サーバーを作る際、以下のような間違いを犯しがちです。
攻撃を受けてしまうダメなコード例(認可サーバー側)
// 認可リクエストを受け取った際の処理(NG例)
$requested_scope = $_GET['scope']; // 攻撃者はここで 'read_profile openid admin_access' と送る
// 検証せずに、そのままトークンを発行してしまう
$token = generate_access_token($user_id, $requested_scope);
このように、「クライアントが要求したスコープ」をそのまま鵜呑みにすると、攻撃者は「admin_access(管理者権限)」を勝手に付け足して、本来の権限を超えた操作ができてしまいます。
—
4. どうやって防ぐの?(開発者のための防衛術)
対策はシンプルです。「管理人があらかじめ許可リスト(ホワイトリスト)を作っておくこと」です。
正しい実装のコード例
// 事前に定義された許可スコープのリスト
$allowed_scopes = ['read_profile', 'openid', 'email'];
$requested_scope = explode(' ', $_GET['scope']);
// 許可されたスコープだけを抽出する(これなら昇格できない!)
$granted_scope = array_intersect($requested_scope, $allowed_scopes);
// 検証済みのスコープのみでトークンを発行する
$token = generate_access_token($user_id, implode(' ', $granted_scope));
さらに、クライアントアプリ側でも「client_id ごとに許可するスコープを固定しておく」のが鉄則です。
—
5. セキュリティの基本:疑うことから始めよう
最後に、現場で役立つマインドセットを一つだけ。
「クライアント(使う側)から送られてくる情報は、すべて泥棒の嘘かもしれないと疑う」
これがセキュリティの第一歩です。
scope パラメーターに限らず、IDや権限に関する値は、必ずサーバー側で「それは本当に許可されている操作なのか?」を厳しくチェックするようにしてくださいね。
今日のまとめ
1. スコープとは、アプリに与える「行動制限(鍵の範囲)」のこと。
2. スコープ昇格とは、それを悪用して権限を広げるズルい手口。
3. 対策は、サーバー側で「許可リスト」と照らし合わせるバリデーションを徹底すること。
最初は難しく感じるかもしれませんが、一度仕組みを理解すれば怖くありません。安全なWebアプリを作るために、一緒に少しずつ学んでいきましょう!
もし、「自分のコードが大丈夫か不安…」というときは、ぜひ今回紹介した「許可リストによる検証」が実装されているか、改めて見直してみてくださいね。それでは、また次回の記事でお会いしましょう!
コメント