ブラウザのURLバーに/orders/1002と入っている。末尾の数字を1001に変えて開き直す。もし他人の注文が表示されたら——それがIDOR(Insecure Direct Object Reference)です。攻撃ツールも専門知識も要りません。数字を書き換えるだけです。
この記事は解説だけでは終わりません。脆弱なコードと修正後のコードを実際にNode.jsで実行し、その出力をそのまま載せています。修正は1行ですが、その1行の有無が「他人の注文明細」と「アクセス拒否」を分けます。
IDORの本体は「アクセス制御チェックの欠落」。この記事のコードは想像ではなく実際に実行した結果で、1行の差がそのまま被害の有無になる。
認可設計とIDORの関係は、OWASPの定義に集約されています。“a vulnerability that arises when attackers can access or modify objects by manipulating identifiers”。URLやパラメータの識別子を操作するだけで、他人のオブジェクトにアクセス・変更できてしまう脆弱性です。
認可設計とIDORを理解する一番の近道は、コードを動かして見ることです。
百聞は一実行に如かずです。以下のコードは編集部が実際にNode.jsで実行したもので、出力もそのまま貼っています。
const orders = [
{ id: 1001, userId: "user-alice", item: "ノートPC", amount: 128000 },
{ id: 1002, userId: "user-bob", item: "モニター", amount: 32000 },
];
// ❌ 脆弱: IDだけで検索。所有者を確認しない
function getOrderVulnerable(orderId) {
return orders.find((o) => o.id === orderId) ?? null;
}
// ✅ 修正: 所有者(userId)も条件に含める
function getOrderFixed(orderId, requestingUserId) {
return orders.find((o) => o.id === orderId && o.userId === requestingUserId) ?? null;
}
=== 脆弱な実装(IDのみで検索) ===
attacker(user-mallory) が bob の注文1002を要求:
{
"id": 1002,
"userId": "user-bob",
"item": "モニター",
"amount": 32000
}
=== 修正後の実装(所有者チェックあり) ===
attacker(user-mallory) が bob の注文1002を要求:
null
bob(user-bob) が自分の注文1002を要求:
{
"id": 1002,
"userId": "user-bob",
"item": "モニター",
"amount": 32000
}
同じgetOrderという関数名で、差は検索条件に userId が入っているかだけです。脆弱な方はmalloryにbobの注文明細(金額つき)をそのまま返し、修正版は他人のデータには null、自分のデータには正しく応答しています。
Insecure Direct Object Reference (IDOR) is a vulnerability that arises when attackers can access or modify objects by manipulating identifiers used in a web application's URLs or parameters.出典OWASP Cheat Sheet Series「Insecure Direct Object Reference Prevention Cheat Sheet」 一次情報を確認2026-08-14 この内容の有効期限2027-02-14
本命は検索条件への所有者ID追加。IDの複雑化とデータセット限定は、それを補強する層として重ねる。
認可設計とIDORの対策は、OWASPがいくつかの層で示しています。“Implement access control checks for each object”。ユーザーがアクセスを試みるオブジェクトごとに、アクセス制御チェックを実装する——実務では3つの層に分けて考えると設計しやすくなります。
// ❌
const order = await prisma.order.findUnique({ where: { id: orderId } });
// ✅
const order = await prisma.order.findFirst({
where: { id: orderId, userId: req.user.id },
});
OWASPはこうも助言しています。全件から検索してIDが一致するかを見るのではなく、最初からユーザーがアクセス権を持つデータセットの中だけを探す——「自分のプロジェクト一覧から取得する」のように、範囲を絞ってから検索する発想です。この考え方はAPI連携の記事で扱った最小権限の原則と同じです。
連番ID(1, 2, 3…)は総当たりで簡単に探索できます。UUIDやランダムな長い文字列に変えると推測は難しくなりますが、OWASPは“access control is crucial even with these identifiers”と釘を刺しています。複雑な識別子はチェックの代わりではなく、チェックに重ねる保険です。
Implement access control checks for each object that users try to access出典OWASP Cheat Sheet Series「IDOR Prevention」(対策の記載部分) 一次情報を確認2026-08-14 この内容の有効期限2027-02-14
自動診断ツールは苦手な領域。2つのテストアカウントとIDの入れ替えだけで、多くのIDORは自分で見つけられる。
認可設計とIDORの不備は「仕様として何が正しいか」を判断する必要があるため、機械的な脆弱性スキャナーでは見つけにくい代表格です。個人開発者が自分でできる、最も確実なテスト手順を示します。
画面のメニューに導線がないデータでも、URLやAPIを直接叩けば取得できてしまいます。「見せていない」と「見えない」は別物です。UI上の非表示は認可の代わりにならないという点は、IDOR対策の中でも見落とされやすい落とし穴です。
同じ課題を持つ会社にとって、動いている設定は「作る時間」を買えるということです。ServiceDockは自作のワークフローやテンプレートを出品できるマーケットプレイスです。手数料や出品の流れは出品者向けページにまとまっています。
出品の仕組みを見る