Forced Browsing et contrôle d'accès côté client : la page admin cachée
Le défi
Voici un tableau de bord client. L'app cache les fonctions admin aux clients avec du CSS, mais les liens partent quand même dans la page que chaque client télécharge. L'un d'eux est réservé au personnel - lisez la source et saisissez l'adresse de cette page admin.
Ce que tu vas apprendre
- Comprendre le forced browsing et la façon dont les attaquants accèdent à des pages jamais liées depuis l'interface visible
- Reconnaître que masquer un élément en CSS (display:none), retirer un élément de menu ou désactiver un bouton relève de la présentation, pas de l'autorisation
- Lire le HTML livré comme le ferait un attaquant, en considérant chaque lien et chaque route du code source comme accessible
- Expliquer pourquoi le contrôle d'accès doit se faire côté serveur, au niveau de la route, et non dans le navigateur
- Rattacher cette faiblesse de contrôle côté client à la catégorie des vulnérabilités de contrôle d'accès défaillant (broken access control)
Compétences testées
Prérequis
- Notions de base sur les liens HTML et le chargement d'une page par un navigateur
- Être à l'aise avec l'affichage du code source d'une page ou l'inspecteur d'éléments d'un navigateur
Comment ça marche
Le forced browsing consiste simplement à demander directement une page ou une route, même si rien dans l'interface visible n'y renvoie. Une application qui masque un contrôle avec du CSS - display:none, une classe qui réduit un élément, un élément de menu retiré au moment du rendu, ou un bouton affiché comme désactivé - n'a changé que ce que le navigateur affiche. Le lien sous-jacent, l'URL et la route sont toujours présents dans le HTML que chaque visiteur télécharge. N'importe qui peut ouvrir l'affichage du code source ou l'inspecteur d'éléments, lire le balisage et suivre la route à la main.
L'erreur fondamentale consiste à traiter le navigateur comme une frontière de confiance. Le navigateur est entièrement contrôlé par la personne qui l'utilise. Le CSS, le filtrage par JavaScript et les nœuds du DOM masqués relèvent de la présentation et du confort, jamais de la sécurité. Si la seule chose qui sépare un client d'une page privilégiée est un style qui masque le lien, alors cette page est en pratique publique : elle n'est qu'à une inspection et un clic de distance.
C'est le cas d'école du contrôle d'accès défaillant. Le serveur sert sans hésiter la route privilégiée à toute session authentifiée, car il ne revérifie jamais qui fait la demande. Masquer le point d'entrée réduit sa découvrabilité, mais découvrabilité n'est pas autorisation. Au moment où la route est demandée, le serveur doit décider si cette session précise est autorisée, et une interface qui se contente de masquer des liens ne prend aucune décision de ce type.
Erreurs fréquentes
- Supposer que, parce qu'un lien n'apparaît pas dans le menu, la route derrière lui est inaccessible - le balisage est livré à tous les navigateurs quel que soit le style appliqué.
- S'appuyer sur
display:none, un bouton désactivé ou un élément de liste retiré comme contrôle d'accès, alors que cela ne change que ce qui est affiché, pas ce qui est servi. - Ajouter des vérifications JavaScript qui masquent ou bloquent l'interface pour les utilisateurs non membres du personnel, en oubliant que l'attaquant contrôle le navigateur et peut contourner entièrement le script.
- Faire confiance à un rôle, un indicateur ou une valeur de cookie fourni par le client pour décider quoi afficher, au lieu de vérifier le vrai rôle côté serveur à chaque requête.
Comment s'en protéger
Appliquez l'autorisation côté serveur, au niveau de la route elle-même, à chaque requête. Avant de servir une page ou une action privilégiée, le serveur doit lire la session authentifiée, récupérer le vrai rôle de cet utilisateur depuis un stockage de confiance, et rejeter la requête si le rôle n'est pas autorisé. Fait correctement, un lien démasqué ou deviné mène simplement à un refus, si bien que la fuite du lien dans le HTML n'a plus d'importance.
- Protégez chaque route admin avec une vérification de rôle côté serveur (refus par défaut ; autorisez uniquement les sessions du personnel vérifiées).
- Revérifiez l'autorisation aussi sur les points d'accès qui exécutent l'action, pas seulement sur la page qui les affiche, car les attaquants appellent ces points d'accès directement.
- Ne faites jamais confiance à un rôle ou une permission envoyé par le client ; déduisez-le de la session côté serveur.
- Considérez le masquage côté client comme un confort d'utilisation ajouté par-dessus de vraies vérifications côté serveur, jamais comme un substitut à celles-ci.