IDOR(安全でない直接オブジェクト参照)は、URLやパラメータのIDを書き換えるだけで他人のデータにアクセスできてしまう脆弱性です。 対策の勘所は、リソースを取り出すときにサーバ側で必ず所有者を確認できているかどうかです。
IDORとは
IDOR(Insecure Direct Object Reference、安全でない直接オブジェクト参照):リクエストに含まれるIDから直接リソースを取り出す際に、そのリソースが本人のものか確認しないことで、他人のデータを操作できてしまう脆弱性です。 所有者チェックの漏れが根本原因になります。
/orders/1024のIDを1025に変えるだけで他人の注文が見えるような、単純だが被害の大きい欠陥です。
情報の閲覧だけでなく、更新や削除のエンドポイントで同じ漏れがあれば、他人のデータを書き換えられます。
APIの認可不備の代表格であり、OWASP API Security Top 10ではBOLA(オブジェクトレベル認可の不備)として1位に挙げられています。
IDORが起きるパターン
典型的な弱点は次のとおりです。
- リクエストのIDだけでリソースを取得し、ログイン中のユーザーが所有者かを確認していない
- 認証(ログインしているか)は見ているが、認可(そのデータにアクセスしてよいか)を見ていない
- 連番のIDを使っており、値を1つずらすだけで他人のリソースを総当たりできる
- ファイル名やユーザー名など、推測しやすい識別子で直接リソースを参照している
- 一覧APIで自分のデータに絞り込む条件を付けず、IDの指定だけで任意の行を返す
共通するのは「リクエストのIDを信用してリソースを返し、それが本人のものかをサーバで確かめていない」という点です。
対策法
原則は「リソースは必ずログイン中のユーザーを起点に絞り込んで取り出す」ことです。
- クエリの条件に現在のユーザー(
current_user)を含め、本人のリソースだけを取得する。これが本命の対策になる - 認証だけで済ませず、操作対象ごとに所有者や権限を確認する認可チェックを入れる
- IDを連番ではなく推測困難な値(UUIDなど)にし、総当たりのコストを上げる(補助策)
- 参照だけでなく更新、削除、一覧のすべてのエンドポイントで同じ所有者チェックを徹底する
推測困難なIDは補助であり、本命はサーバ側での所有者に基づく絞り込みです。
リソースを扱う全エンドポイントを洗い出し、current_user起点の取得に統一するのが費用対効果の高い進め方になります。
Rails での事例
危険な実装は、リクエストのIDをそのままモデルの検索に渡す形です。
# 危険:ログイン済みなら誰の注文でも取得できる
def show
@order = Order.find(params[:id])
end
Order.find はテーブル全体からの検索であり、URL の ID を書き換えれば他人の注文が返ります。
直し方は、取得の起点を current_user の関連に変えることです。
def show
@order = current_user.orders.find(params[:id])
end
これで発行される SQL に user_id = ? の条件が加わり、他人の ID を指定しても ActiveRecord::RecordNotFound(404)になります。
所有者チェックを if @order.user_id == current_user.id のような後付けの分岐で書く方法もありますが、書き忘れがそのまま穴になるため、関連経由の取得に統一するほうが漏れにくくなります。
更新と削除でも同じ形にします。
def destroy
current_user.orders.find(params[:id]).destroy!
end
管理者だけ全件を扱えるようにしたい場合も、Order.find へ戻すのではなく、Pundit や CanCanCan のような認可ライブラリでロールごとのスコープを定義し、取得経路を一元化します。
まとめ
IDOR対策の要点を整理します。
- 成立条件は「リクエストのIDを信用してリソースを返し、それが本人のものかをサーバで確かめていないこと」。認証(ログイン確認)と認可(アクセス可否の確認)の混同が典型的な背景にある
- 本命の対策は、現在のユーザーを起点にした絞り込み(
current_user.orders.findのような関連経由の取得)。後付けのif分岐は書き忘れがそのまま穴になる - 参照だけでなく更新・削除・一覧まで、リソースを扱う全エンドポイントで同じ形に統一する
- UUIDなど推測困難なIDは総当たりのコストを上げる補助策で、所有者チェックの代わりにはならない
- 管理者向けの全件アクセスは、認可ライブラリでロールごとのスコープとして定義し、取得経路を一元化する
既存コードの点検は、Model.find(params[:id]) のような「テーブル全体からの直接取得」をgrepで洗い出すところから始めるのが近道です。
関連して読める記事
CSRFも「認証は通っているのに、意図しない操作が成立してしまう」という点でIDORと地続きの脆弱性です。SQLインジェクションは、同じくリクエストの値を検証しないままデータベースに渡すことで起きます。あわせて点検すると、リクエスト由来の値の扱いをまとめて見直せます。

CSRF(クロスサイトリクエストフォージェリ)とは?起きるパターンと対策法
CSRF(クロスサイトリクエストフォージェリ)の仕組みと起きるパターン、CSRFトークンとSameSite Cookieを軸にした対策を整理します。Railsで検証を外してしまう skip_before_action の罠と、React(TypeScript)からのトークン送信ヘッダの組み込み方を、危険なコードと安全な書き方の具体例で示します。
2026年7月23日
SQLインジェクションとは?起きるパターンと対策法
SQLインジェクションの仕組みと起きるパターン、そしてプレースホルダ(パラメータ化クエリ)を軸にした対策を整理します。Rails(Active Record)で穴が開く where の文字列展開と order のカラム名、その安全な書き方を具体的なコード例で示します。
2026年7月22日