Failles IDOR (Insecure Direct Object Reference) : principes, attaques, mesures et tests sécurité

Les IDOR (pour Insecure Direct Object Reference) sont des vulnérabilités très répandues dans les applications web au même titre que les failles XSS ou les injections SQL. Affiliées aux problèmes de droits, les failles IDOR sont en effet parmi celles que nous découvrons et exploitons le plus couramment lors de nos tests d’intrusion d’applications web.

Principes, scénarios d’attaques et exploitations, nous vous présentons dans cet article une vue d’ensemble des IDOR, ainsi que les bonnes pratiques sécurité et tests de droits à réaliser pour prévenir les risques d’attaques.

Qu’est-ce qu’une vulnérabilité IDOR ?

Une vulnérabilité de type IDOR est un problème de contrôle de droits, qui apparait lorsqu’une référence directe à un objet (fichiers, informations personnelles, etc.) peut être contrôlée par un utilisateur.

Très souvent, ce type de vulnérabilité permet de s’accorder des privilèges de façon horizontale (autrement dit permettre d’accéder à des informations d’utilisateurs ayant les mêmes droits) et, dans de plus rares cas, élever ses privilèges.

Prenons par exemple le cas d’une application SaaS incluant des fonctionnalités de lecture et d’écriture de factures, avec des accès et donc des droits utilisateurs prédéfinis.

Imaginons maintenant que les contrôles de droits sont mal configurés ce qui permettrait à un utilisateur d’accéder (en lecture et/ou en écriture) aux factures d’autres utilisateurs de l’application en modifiant tout simplement son URL.  

En effet, l’utilisateur pourrait consulter une de ses factures via l’URL suivante :

https://www.example.com/factures/002546

Et ensuite, avec ou sans l’aide d’un outil, il pourrait modifier les paramètres d’URL. Notons au passage que ce type d’exploitation est très facile avec un outil de brute force par exemple pour des raisons de rapidité et de configuration de paramètres.

Prenons ici, le cas le plus simple à savoir modifier l’identifiant de sa facture.

https://www.example.com/factures/002746

Si ce fichier est bien disponible dans la base de données (via cet ID) et qu’aucun contrôle de droits n’est effectué, on parlera donc d’une IDOR. De fait, l’impact de ce type de vulnérabilités peut être critique en fonction de la sensibilité des données.

Pour plus d’informations, nous vous renvoyons vers ce Write-Up dans lequel nous présentons un cas concret d’une exploitation multi-tenant de GraphQL via une IDOR :

Exploitation d’un manque de contrôle de droits sur GraphQL

Comment prévenir les IDOR et les attaques les exploitant ?

Pour prévenir les IDOR, deux approches peuvent être adoptées :

  • Utiliser des références indirectes, par utilisateur ou par session
  • Vérifier les droits d’accès pour les références directes

Utiliser des références indirectes par utilisateur ou par session

Dans ce cas de figure, il s’agit de faire en sorte que l’application web fournisse à un utilisateur des URLs et paramètres associés qui n’ont de sens que dans la session de ce dernier.

Revenons sur notre exemple : l’utilisateur pourra accéder à des factures en utilisant une URL du type :

https://www.example.com/mes-factures/36

Mais en fonction de la personne connectée, la même URL n’affichera pas la même facture, rendant impossible tout accès non autorisé à des factures d’autres utilisateurs.

En effet, à l’intérieur de l’application l’URL https://www.example.com/mes-factures/36 fera référence à une facture qui n’a pas 36 comme identifiant, mais peut être ffc61035-b579-44e0-b7fc-199bb005cdde. Par ailleurs, cet identifiant doit être généré de façon aléatoire et doit être suffisamment long (indevinable donc) pour que la protection mise en place soit efficace.

Ainsi, la correspondance entre la référence indirecte 36 et la facture reste invisible pour l’utilisateur.

Seulement, Il faut faire attention à bien implémenter cette solution. L’erreur serait de laisser la possibilité à l’utilisateur de saisir une référence directe au lieu d’une référence indirecte.

L’exemple le plus courant concerne l’accès à ses informations personnelles. De nombreuses applications utilisent endpoint/me pour renvoyer les informations personnelles d’un utilisateur.

Dans ce cas de figure, le serveur va alors regarder le jeton de session de l’utilisateur faisant la requête pour en déduire la référence à l’objet associé à ce compte. Si un attaquant fournit directement un identifiant dans l’URL, il peut dans certains cas contourner le contrôle en place sur le jeton de session et donc accéder aux données d’autres utilisateurs.

Imaginons l’URL suivante https://example.com/infos/me qui renvoie les données d’un utilisateur. Pour un utilisateur d’identifiant 1340, le serveur peut aussi accepter https://example.com/infos/1340 pour renvoyer les mêmes informations.

Ici, une IDOR peut apparaitre si aucun autre contrôle de droit n’est réalisé, car il suffirait à un attaquant de faire une requête sur https://example.com/infos/1341 pour accéder aux informations d’un autre compte.

L’utilisation d’une référence indirecte oblige donc le serveur à regarder le jeton de session ou les cookies. De fait, le jeton de session ne doit pas être falsifiable pour éviter tout risque d’IDOR voire le vol de compte dans ce cas précis.

Vérifier les droits d’accès pour les références directes

Utiliser des références indirectes n’est pas toujours possible. Cependant, il est envisageable d’utiliser des caractères aléatoires pour les références, rendant beaucoup plus difficile le fait de deviner des URLs. Cependant, dans beaucoup de situations, il sera nécessaire de contrôler les droits d’accès à une ressource donnée.

Revenons sur l’exemple de notre application. Si celle-ci intègre une fonctionnalité de partage de factures, l’URL devra être la même pour plusieurs utilisateurs afin de faciliter les échanges, mais ne devra pas être accessible à tout le monde.

Dans ce cas de figure, un mécanisme de gestion des droits d’accès devra être mis en place.

L’URL de partage pourra par exemple être :   

http://www.example.com/factures/bruce/dga7asg5s0sbaeaa7sba

Et essayer d’accéder à cette URL devra déclencher une vérification des droits afin de s’assurer que l’accès est autorisé. En effet, il ne faut pas se reposer uniquement sur le fait d’avoir un identifiant aléatoire et long.

Ce que l’on pense être un identifiant totalement aléatoire peut ne pas l’être tant que ça. Prenons le cas de l’identifiant suivant pour illustrer notre propos : 001Do000002LlTAIA0.

Ici (cas rencontré lors d’un pentest), les 5 premiers caractères décrivent le type d’objet (comme « Account »), les 5 suivants sont réservés pour d’éventuels fonctionnalités additionnelles et les 5 derniers sont un identifiant unique. L’aléatoire est alors grandement réduit et les possibilités de brute force de l’identifiant sont bien présentes.

De plus, même si les deux conditions (indevinable et long) sont réunies, il faut veiller à ce que les identifiants ne fuitent pas dans l’application.

Par exemple, il nous est déjà arrivé lors de la création d’un compte que l’identifiant – par ailleurs un email ici – se retrouve dans la réponse du serveur si l’email est déjà utilisé. L’attaquant a donc besoin de seulement cibler un compte avec une adresse email qu’il connaît pour obtenir des informations si le contrôle de droit n’est pas correctement réalisé.

Enfin, il existe un cas spécifique où des IDOR peuvent apparaître : lorsqu’une application nécessite de partager un lien vers un utilisateur sans compte donc non authentifié. L’accès non authentifié est alors nécessaire et la seule protection possible réside dans l’identifiant choisi. Ainsi, les solutions recommandées précédemment doivent impérativement être mises en œuvre.

Pour réduire encore un peu plus le risque, le rate limiting peut être implémenté sur chaque endpoint sensible.

Comment tester les contrôles de droits et identifier des IDOR ?

Les tests de contrôle de droits utilisateurs sont une étape incontournable lors d’un pentest d’autant plus qu’il y a régulièrement des vulnérabilités sur ce mécanisme critique. Pour un pentest web, l’outil BURP convient parfaitement pour réaliser ces tests. Et pour ce faire, deux extensions sont disponibles : AuthMatrix et AuthAnalyzer.

Le principe commun de ces extensions est de rejouer les requêtes qui pourrait comporter des problèmes de droits avec différents jetons de session. En général, nous utilisons un compte avec les droits les plus élevés (souvent un administrateur), un compte avec des droits utilisateurs simple et un utilisateur non authentifié.

Ainsi, l’extension va rejouer toutes les requêtes avec les différents jetons de session fournis. Un code couleur nous permet ensuite d’identifier les éventuels manques de contrôle de droits.

Dans l’exemple ci-dessous, 3 sessions différentes ont été fournies à AuthMatrix : admin, collaborator et un jeton de session non valide – unauthenticated donc.

L’utilisateur coche les requêtes que chaque utilisateur a le droit de faire (il faut une bonne compréhension de l’application pour cela). Et si toutes les requêtes sont en vert, cela signifie qu’il n’y a pas de manque de contrôle de droit.

Pour revenir sur les spécificités des 2 extensions. D’un côté, nous avons AuthMatrix qui permet une sélection plus précise des requêtes à analyser. Cette extension est pratique lorsqu’il y a peu de requêtes à étudier ou lorsque des requêtes sensibles (comme des requêtes pouvant créer, modifier ou supprimer des données) ne doivent pas être rejouées. Aussi, cette extension permet aussi de tester les vulnérabilités CSRF.

AuthAnalyzer quant à lui est plus pratique lorsque de nombreuses requêtes doivent être contrôlées. Après avoir configuré les sessions que nous voulons utiliser, l’extension va rejouer toutes les requêtes que nous effectuons depuis notre navigateur avec les jetons de session fournis.

Ci-dessous l’interface d’AuthAnalyzer dans Burp, avec les 3 mêmes comptes de l’exemple avec AuthMatrix. On retrouve 3 types de réponses : SAME révélant que la réponse est identique à la réponse obtenue avec le compte de la requête originelle, SIMILAR signifiant que le corps de la réponse ressemble mais les données ne sont pas identiques et DIFFERENT montrant une grande différence entre la réponse de base et celle obtenue avec le compte en question.

Conclusion

La gestion des droits reste un exercice délicat. En effet, malgré les essais de configuration, il n’est pas rare de trouver des failles IDOR lors d’un pentest. Seulement, il n’existe aucun outil automatisé permettant de les identifier facilement car il faut bien connaître la logique d’une application pour savoir si le serveur effectue le bon contrôle de droit ou non. Cependant pour tester les possibilités de contournement de contrôle de droits, les extensions Burp (AuthMatrix et AuthAnalyzer) sont incontournables.

Pour prévenir les IDOR, il est essentiel de contrôler les droits d’accès des utilisateurs aux divers objets de l’application qui doivent avoir des identifiants longs et aléatoires.

Auteur : Julien BRACON – Pentester @Vaadata