Une page sur six : quand le client choisit les octets qu'il a le droit de voir
Le défi
La console de support de Northgate montre aux relecteurs un seul paragraphe d'un rapport d'incident, la section impact client, et rien d'autre. Le caviardage n'est pas dans le document. La console va chercher exactement la tranche qu'elle veut avec un en-tête Range et affiche ce qui revient, et le service de stockage honore n'importe quelle plage demandée. Le rapport indique que trois identités de service pouvaient supprimer dans l'archive des relevés ce matin-là. Parcourez le document et trouvez laquelle a réellement émis l'appel de suppression.
Ce que tu vas apprendre
- Expliquer ce que fait l'en-tête HTTP Range et qui choisit sa valeur
- Reconnaître qu'un caviardage implémenté par l'appelant n'en est pas un
- Parcourir un objet page par page à partir d'une erreur de plage non satisfiable
- Lire une chronologie CloudTrail pour distinguer corrélation et causalité
- Expliquer pourquoi le stockage d'objets doit autoriser l'objet, pas la plage d'octets
Compétences testées
Prérequis
- La structure d'une requête HTTP
- Ce qu'est un en-tête de requête
Comment ça marche
Range permet à un client de demander une partie d'une ressource plutôt que sa totalité. Cet en-tête existe pour qu'un lecteur vidéo puisse se positionner dans la vidéo et qu'un téléchargement puisse reprendre, et le serveur répond par 206 Partial Content avec uniquement ces octets. Tout dans cet échange est piloté par le client : il indique les décalages, et un serveur qui prend en charge les plages les renvoie.
C'est ce qui fait de Range un endroit désastreux pour placer une décision de sécurité. Ici, la console envoie bytes=2048-2559 parce que c'est le paragraphe que le relecteur est censé lire, et l'interface autour donne une impression de verrouillage convaincante. Mais la question d'autorisation à laquelle le service de stockage a répondu était : cette session peut-elle lire cet objet, et il a répondu oui. Quels octets de l'objet n'a jamais été une question du tout.
Le même schéma apparaît partout où un client restreint une réponse et où cette restriction est ce qui protège un secret : un paramètre fields=, une taille de page, une fenêtre de dates, une liste de colonnes. Si le serveur avait renvoyé la totalité à une requête qui demandait la totalité, alors la restriction est un choix d'affichage, pas un contrôle.
Erreurs fréquentes
- Répondre svc-retention-audit. Il liste des objets et lit des tags dans les mêmes secondes, ce que fait un job de rétention chaque nuit. Il n'émet jamais de suppression.
- Répondre svc-statement-render. Il n'appelle jamais que GetObject, et son 404 à 04:13:02 est le premier symptôme, pas la cause.
- S'arrêter au résumé. La page 0 nomme volontairement les trois candidats et renvoie à la section 2. La chronologie est la preuve.
- Modifier le chemin ou le cookie. Les deux sont protégés et aucun des deux n'est la faille. Le seul champ qui compte ici est la plage.
- Demander bytes=0-. Une plage ouverte est refusée pour ce profil. Les requêtes paginées ne le sont pas.
Comment s'en protéger
Autorisez la ressource, et ne donnez à l'appelant que ce qu'il a le droit d'avoir.
- Faites extraire par le serveur la section visible par le relecteur et renvoyez-la comme un document à part entière. Si les octets ne quittent jamais la limite de confiance, aucun en-tête ne peut les demander.
- Stockez les sections sensibles sous forme d'objets séparés avec leurs propres politiques, afin qu'une requête de plage ne puisse pas franchir une ligne de classification.
- Si des réponses partielles sont réellement nécessaires, validez la plage demandée par rapport à ce que le profil de cet appelant est autorisé à lire, et journalisez chaque requête qui en sort.
- Gardez aussi la faille sous-jacente à l'esprit : CHG-9921 a attaché une politique de suppression au niveau du bucket pour un job qui n'avait besoin que d'un préfixe. Limitez les permissions d'écriture et de suppression au préfixe le plus étroit qui fonctionne.