Revue de code inversée : disculper le seul gestionnaire réellement sûr

Sécurité Web & API Niveau 4/4 ~7 min 6 septembre 2026

Le défi

Quatre gestionnaires du même service de comptes, écrits dans le même style par la même équipe, tous décorés de login_required et tous lisant des données de la requête. Trois d'entre eux contiennent une vulnérabilité réelle et différente : l'un est injectable, l'un réfléchit du balisage contrôlé par l'attaquant, et l'un ira chercher n'importe quelle adresse que vous lui indiquerez. Le quatrième fait tout correctement. C'est l'inverse de l'exercice habituel : savoir nommer un bug ne suffit pas, il faut disculper un gestionnaire, donc démontrer que les trois autres sont fautifs. Soumettez le nom de la seule fonction qui est sûre.

Ce que tu vas apprendre

  • Examiner le code par élimination plutôt qu'en repérant un seul sink évident
  • Reconnaître une injection SQL construite par interpolation de f-string
  • Reconnaître un XSS réfléchi issu d'une concaténation non échappée dans une réponse HTML
  • Reconnaître un SSRF dissimulé derrière une vérification d'URL limitée au schéma
  • Expliquer pourquoi login_required relève de l'authentification et non de l'autorisation
  • Identifier les propriétés qui rendent réellement un gestionnaire sûr

Compétences testées

Revue de code sécuriséeClassification des vulnérabilitésSécurité des applications web

Prérequis

  • Lecture de code Python et du routage d'un framework web
  • Connaissance de l'injection SQL, du XSS et du SSRF

Comment ça marche

La plupart des exercices de revue de code demandent de trouver le bug, ce qui récompense la reconnaissance de motifs : repérer une fonction dangereuse, la nommer, passer à la suite. La revue réelle a la forme inverse. Il faut rendre compte de chaque chemin avant de pouvoir valider quoi que ce soit, et un gestionnaire n'est disculpé qu'une fois que l'on a expliqué pourquoi chacune de ses entrées ne peut pas vous nuire.

Ces quatre gestionnaires sont volontairement uniformes. Ils proviennent d'un seul fichier, partagent le même style, portent tous login_required, et lisent tous une entrée influencée par l'attaquant. Le décorateur est le piège : il prouve seulement que l'appelant est connecté, rien de plus. Il ne paramètre aucune requête, n'échappe aucune réponse et ne valide aucune destination.

get_order interpole order_id dans du SQL via une f-string. La route la capture comme une chaîne de caractères, si bien qu'un payload atteint la requête intact et peut terminer la condition, ce qui casse à la fois la requête et le contrôle de propriété sur user_id logé dans la même chaîne. render_receipt concatène le paramètre note dans du balisage renvoyé en text/html, ce qui constitue un XSS réfléchi. fetch_logo exige que l'URL commence par https:// puis la récupère depuis le serveur, ce qui autorise les adresses de métadonnées link-local et les noms de services internes : le contournement SSRF classique.

update_contact est celui qui survit, et il survit grâce à trois propriétés précises : une entrée validée par une expression régulière en correspondance complète et une limite de longueur avant usage, une requête paramétrée si bien que la valeur ne devient jamais du texte de requête, et une clause WHERE indexée sur session['user_id'] si bien que la ligne modifiée est choisie par le serveur, et non par l'appelant.

Erreurs fréquentes

  • Répondre get_order parce qu'il vérifie user_id. Ce contrôle se trouve dans la même f-string injectable, si bien qu'un payload peut le neutraliser. Une clause de propriété qu'un attaquant peut modifier n'est pas une clause de propriété.
  • Répondre fetch_logo parce qu'il valide l'URL. Vérifier le schéma n'est pas valider la destination. https://169.254.169.254/ passe ce test.
  • Répondre render_receipt parce qu'order_id utilise le convertisseur int. L'identifiant est correct ; c'est le paramètre note qui atteint la réponse HTML sans échappement.
  • Considérer login_required comme le facteur décisif. Les quatre gestionnaires l'ont, il ne peut donc pas les différencier.
  • S'arrêter à la première vulnérabilité trouvée. La question demande quel gestionnaire est sûr, il faut donc examiner les quatre.

Comment s'en protéger

Chacun des trois gestionnaires défaillants a un correctif bien établi, et update_contact illustre déjà le schéma que les autres devraient suivre.

  • Injection. Utilisez toujours des paramètres liés. Ne construisez jamais de SQL avec des f-strings ou de la concaténation, et contraignez les captures de route avec le bon convertisseur, par exemple <int:order_id>.
  • Cross-site scripting. Effectuez le rendu via un moteur de templates avec échappement automatique contextuel plutôt qu'en concaténant des chaînes, et ajoutez une Content-Security-Policy pour qu'un échappement manqué ne soit pas immédiatement exploitable.
  • SSRF. Résolvez le nom d'hôte et rejetez les plages privées, loopback et link-local, revérifiez après les redirections, utilisez une liste blanche d'hôtes autorisés, et faites passer les requêtes sortantes par un proxy de sortie.
  • Autorisation. Restreignez chaque requête au principal de session, comme le fait update_contact, afin que la propriété soit imposée par le serveur plutôt qu'affirmée par la requête.
  • Processus. Ajoutez du linting pour le SQL construit par chaînes et la construction de réponses non échappées, afin que ces schémas échouent en CI plutôt qu'en revue.

Solution complète

Les membres Pro et Max débloquent la solution complète étape par étape.

Passer Pro

Statistiques de la communauté

120 résolutions
78% taux de réussite
Hodanalo Premier sang

Hacks du jour associés

29 000+ Hackers 100+ Labs & Cours Gratuit
Commencer Gratuitement