CyberFix Note
セキュアコーディング

IDORとアクセス制御の不備、識別子を差し替えられても守れる認可の作り方

対象の目安: Web/APIを実装する開発者・実務

リク編集長 / セキュリティ全般・戦略
・ 約10分で読めます
IDORとアクセス制御の不備、識別子を差し替えられても守れる認可の作り方

注文の詳細ページやユーザーのプロフィールAPIのように、Webアプリやそのバックエンドは「どの資源を返すか」をURLやパラメータの中の識別子で決めています。この識別子で資源を取り出すとき、取り出す前に「この資源を、いま要求してきた本人がアクセスしてよいか」を確かめていないと、識別子を他人のものに書き換えるだけで他人のデータへ到達されてしまいます。これがIDOR(Insecure Direct Object Reference、安全でない直接オブジェクト参照)です。

この記事は、Webアプリやそのバックエンドを実装する開発者に向けて、IDORがなぜ成立するのかという機構から、認証と認可の切り分け、OWASPの分類での位置づけ、そしてサーバー側の認可を軸にした対策までを順に整理します。攻撃の手順そのものではなく、どこに認可の判断を置けば防げるのかに焦点を当てます。

IDORが成立する機構

IDORは、サーバーがリソースを識別子(URLやパラメータ中のidなど)で受け取ったとき、その要求元が当該リソースにアクセスしてよいかをサーバー側で確かめずに直接参照して返す、または操作するために成立します。攻撃者が自分の識別子を他人の識別子に差し替えると、そのまま他人のデータへ到達できます。

具体的に見ます。あるアプリが、注文の詳細を次のようなURLで返すとします。

GET /orders/1024

サーバーがここで「ログイン済みかどうか」だけを見て、受け取った1024という注文を無条件に読み出して返すと、利用者が数字を1025に変えるだけで別人の注文が返ってしまいます。原因は、識別子が「本人の資源を指す名前」ではなく「任意の資源を選べるパラメータ」として扱われ、その選択に対する許可の確認が抜けている点にあります。PortSwiggerの解説も、アプリケーションがアクセス制御の判断にユーザー入力の値を使いながら、その値に対する認可を確かめないときにこの参照が成立する、と説明しています。

MITREのCWE-639(Authorization Bypass Through User-Controlled Key、利用者が制御する鍵による認可の回避)は、この構造を、システムが利用者の制御下にある鍵で資源を特定しながら本人の権限を検証しないために、他者の資源へアクセスされうる欠陥として定義しています。より広い上位概念はCWE-284(Improper Access Control、不適切なアクセス制御)です。

認証と認可の違いから見た位置づけ

IDORを正しく防ぐには、認証と認可を分けて考える必要があります。認証は「要求元が誰か」を確かめる処理で、認可は「その誰かが、この資源にこの操作をしてよいか」を確かめる処理です。IDORはログインが通っている(認証は成立している)のに、資源ごとの許可(認可)を確かめていない状態で起きます。

認証と認可の切り分けは、別記事で基礎から整理しています。

あわせて読みたい

認証と認可の違い。Authentication と Authorization を基礎から整理する

OWASPの分類では、この欠落はアクセス制御の不備としてまとめられています。

OWASP Top 10 2025のA01:2025「Broken Access Control」は、アクセス制御は利用者が与えられた権限の外で行動できないようにポリシーを強制するものだと定義し、代表的な欠陥の一つとして「一意な識別子を渡すだけで他人のアカウントの閲覧や編集ができてしまう(安全でない直接オブジェクト参照)」を挙げています。関連するCWEとしてCWE-639などが列挙されています。2021年版でもBroken Access ControlはA01でした。

APIの世界では、同じ欠落がBOLA(Broken Object Level Authorization、オブジェクトレベル認可の不備)という名前で整理されています。

OWASP API Security Top 10 2023のAPI1:2023「Broken Object Level Authorization」は、リクエストに含まれるオブジェクトのIDを操作されることで、本来アクセスしてはならないデータへ到達されうる問題を指します。APIではオブジェクトIDがエンドポイントで直接扱われるため、この認可の欠落がとりわけ生じやすいとされています。

呼び名は文脈で変わりますが、機構は同じで、識別子で選ばれた資源に対する認可の判断が抜けている点が共通します。

典型的な現れ方

IDORは、水平方向と垂直方向のどちらの権限昇格としても現れます。水平方向は、同じ権限レベルの他人の資源へ横に移るもので、自分の注文IDを他人の注文IDに差し替えて閲覧するのがこれにあたります。垂直方向は、本来は上位のロールにしか許されない資源や操作へ届いてしまうもので、一般利用者の識別子を管理用のオブジェクトに向けて操作できてしまう場合が該当します。

現れる場所も限りません。GETで資源を読み出す経路だけでなく、更新系のPUTやPATCH、削除のDELETEでも同じ欠落は起きます。読み取りより書き込みや削除で認可が抜けているほうが、影響は大きくなります。ファイル名やパスを識別子として扱う場合は、資源の選択という同じ問題がパスの解決という別の形でも現れます。パスに固有の落とし穴は別記事で扱っています。

あわせて読みたい

パストラバーサルとは何か。基準ディレクトリの外へ解決されるパスの脆弱性と根本対策を解説

なお、実データを用いた検証は、許可された自組織の環境に限って行ってください。他人が運用するサービスに対して識別子を差し替えて試す行為は、権限のない範囲では行いません。

なぜ認可チェックが抜けるのか

IDORが残ってしまう背景には、いくつか共通の要因があります。一つは、認可チェックの実装漏れです。エンドポイントごとに所有者やテナントを確かめる処理を書く必要があるのに、認証だけを共通のミドルウェアで済ませ、資源単位の確認を各処理に書き忘れる形です。エンドポイントが増えるほど、抜けは起きやすくなります。

もう一つは、識別子を連番などでそのまま外部に露出していることです。露出それ自体が脆弱性なのではなく、露出した識別子に対して認可を確かめていないことが問題です。連番だと差し替えの候補が見つけやすいだけで、根の原因は認可の欠落にあります。

三つ目は、制御をクライアント側だけに置いてしまうことです。画面に他人の資源へのリンクやボタンを表示しなければ安全だ、という発想は認可ではありません。画面の見た目を絞っても、リクエストを直接組み立てて送れば、サーバーはそのまま処理してしまいます。判断は必ずサーバー側に置く必要があります。

対策の組み立て方

対策の中心は、資源を返す前や操作する前に、サーバー側でオブジェクト単位の認可を毎回確かめることです。以下の順で組み立てると、抜けを減らせます。

  1. 1

    オブジェクト単位の認可をサーバー側で毎回行う

    識別子で資源を取り出したあと、その資源の所有者やテナント、必要なロールを、要求元の認証情報と突き合わせて確認します。「本人の資源だけを検索条件に含める」形にすると、他人の識別子を渡されても資源が見つからず、確認と取得を一体にできます。

  2. 2

    既定は拒否にする

    認可の判断が明示的に「許可」を返さない限り、アクセスを通さないようにします。新しいエンドポイントを追加したときに、確認を書き忘れても既定で拒否側に倒れる設計にしておくと、実装漏れが露出につながりにくくなります。

  3. 3

    認可を一箇所に集約する

    エンドポイントごとに書き散らすのではなく、認可の判断を共通の層や仕組みにまとめ、各処理はそこを呼ぶ形にします。判断が一箇所に集まっていれば、抜けの確認もテストも進めやすくなります。

  4. 4

    必要なら間接参照を使う

    外部にはセッション単位で割り当てた参照値を見せ、実際の資源IDへの対応をサーバー側の対応表で解決する方法です。これは差し替えを起こしにくくする緩和であり、対応表を引いたあとも所有者やロールの確認は省けません。

  5. 5

    別ユーザーの識別子で検証する

    許可された自組織の環境で、あるユーザーとしてログインした状態から、別ユーザーの識別子を指す要求を送り、拒否されることを確かめます。読み取りだけでなく更新や削除の経路も同じ観点で確認します。

水平方向と垂直方向のどちらの昇格も、対象オブジェクトと操作に応じた認可で塞ぐのが基本です。所有者やテナントの一致に加え、共有関係や必要なロールなど、そのオブジェクトに適用すべき条件をサーバー側でまとめて判定します。所有者の確認だけでは別テナントの管理者による越境などを防ぎきれないため、判定の条件をオブジェクトと操作ごとに設計します。API設計でこの認可の抜けが生じやすい点は、関連記事でも整理しています。

あわせて読みたい

APIセキュリティの基本。認証認可・レート制限・入力検証とOWASP API Top 10で守る

推測しにくい識別子という誤解

対策を検討すると、識別子を連番のような推測しやすい値からUUIDのような推測しにくい値に変えれば防げる、という考えに行き着きがちです。ここには注意が必要です。

注意

UUIDなど推測しにくい識別子の採用は、差し替えの候補を見つけにくくする緩和にとどまり、認可チェックの代わりにはなりません。識別子はログやリファラ、共有されたURL、別のAPI応答などから漏れることがあり、値が知られれば、認可を確かめていないサーバーはそのまま資源を返します。推測しにくいIDは補助として使い、資源ごとの認可はそれとは別に必ずサーバー側で行ってください。

守りの土台はあくまで認可の判断です。識別子の形は、その判断を補う位置に置きます。

まとめ

IDORは、識別子で選ばれた資源に対して、要求元がアクセスしてよいかをサーバー側で確かめないために成立します。呼び名はWebのA01 Broken Access ControlでもAPIのBOLAでも、機構は同じです。防御の要点は、資源を返す前にオブジェクト単位で所有者やロール、テナントを毎回確かめること、既定を拒否にすること、判断を一箇所に集約することです。IPAの「安全なウェブサイトの作り方」でも、アクセス制御や認可の不備は代表的な注意点として取り上げられています。

IDOR対策チェックリスト

  • 識別子で資源を取り出したあと、所有者やテナント、ロールをサーバー側で確認しているか
  • 認証(ログイン済みか)だけで通していないか(資源ごとの認可を別に確かめているか)
  • 認可の判断が既定で拒否側に倒れる設計になっているか
  • 認可の判断を一箇所に集約し、各エンドポイントがそこを呼んでいるか
  • 更新系(PUT/PATCH/DELETE)の経路でも認可を確かめているか
  • 水平方向と垂直方向のどちらの権限昇格も同じ確認で塞げているか
  • 推測しにくいIDを認可の代わりにしていないか
  • 許可された自組織環境で、別ユーザーの識別子を試して拒否されることを確認したか

出典・参考

この記事をシェア

関連する記事