Comprendre le mécanisme
Une donnée traverse plusieurs contextes : SQL, HTML, chemins, logs ou commandes. Un encodage adapté à l’un ne protège pas les autres. Pour HTML, l’échappement de sortie conserve les données comme texte ; pour SQL, les valeurs sont liées ; pour une commande, réduisez d’abord le besoin d’exécution et évitez la construction libre d’une ligne shell. L’autorisation répond à la question « cet acteur peut-il agir sur cette ressource ? », distincte de l’authentification.
Raisonner et vérifier
Hachez les mots de passe avec une API dédiée et vérifiez-les avec password_verify. Un token CSRF protège une action contre des déclenchements intersites indésirables, pas contre toutes les attaques. Évitez de désérialiser des objets issus d’une source non fiable. Les erreurs publiques doivent être utiles sans divulguer secrets, traces SQL ou tokens ; les journaux gardent des événements minimisés et un identifiant de corrélation.
Vérifier un mot de passe selon son format
password_hash crée un format adapté à la vérification d’un secret humain, avec ses paramètres et son sel. password_verify vérifie ensuite une valeur présentée contre ce format. Un hash rapide comme MD5 ne fournit pas un coût approprié de résistance aux essais hors ligne. Après succès, une politique peut demander un rehash ; un échec ne doit jamais remplacer la preuve stockée par la mauvaise valeur reçue.
Understand this common mistake
MD5 direct fournit un coût adaptatif approprié.
Une fonction dédiée doit ralentir et paramétrer les essais.
La sortie détermine le contrôle pertinent
Une chaîne peut être destinée à du texte HTML, une URL, du JavaScript ou une valeur SQL. Ces contextes ne partagent pas une protection universelle. htmlspecialchars ne transforme pas une concaténation SQL en requête paramétrée. Pour un libellé navigateur, une insertion textuelle peut éviter l’interprétation HTML. Commencez chaque revue par le point d’utilisation de la donnée, puis choisissez le contrôle qui correspond à ce contexte précis.
Understand this common mistake
Un échappement HTML sécurise tout SQL.
Les contextes exigent des contrôles différents.
L’objet fait partie de l’autorisation
Un utilisateur connecté n’obtient pas automatiquement l’accès à une réservation dont il connaît l’identifiant. Les UUID et paramètres SQL protègent d’autres propriétés que l’isolation métier. Résolvez la ressource dans le bon tenant et vérifiez l’opération demandée. Le test doit essayer deux acteurs avec le même identifiant et observer le refus sans effet du second ; une interface qui masque le lien ne bloque pas un client direct.
Understand this common mistake
Une identité connectée peut lire toute ligne par son ID.
L’authentification ne donne pas tous les droits.
Les références reçues ne donnent pas accès au système
Un chemin fourni par le client ne doit pas sélectionner librement un fichier serveur. Préférez un identifiant métier résolu dans un stockage maîtrisé, avec autorisation avant lecture. La même prudence vaut pour une préférence sérialisée : un texte reçu ne doit pas reconstruire arbitrairement des objets et leurs comportements. Dans une nouvelle API, un format de données simple avec validation explicite limite les capacités accordées au parsing.
Understand this common mistake
Un chemin client absolu constitue une permission de lecture.
La sélection du fichier doit être contrôlée.
Un token décodé n’est pas une identité validée
Le payload d’un JWT peut être lisible sans que sa signature soit correcte. Avant d’utiliser sub ou role, appliquez le contrat du profil : preuve cryptographique, clé et algorithme admis, issuer, audience, types et règles temporelles nécessaires. Ces contrôles établissent une identité utilisable dans ce contexte. L’autorisation sur la ressource vient ensuite ; une signature valide ne donne pas une permission universelle.
Understand this common mistake
Un payload décodé suffit à accorder admin.
Le parsing n’établit pas l’authenticité.
Un upload consomme plusieurs budgets
La limite du formulaire ne contrôle pas à elle seule le proxy, PHP, le disque ou la décompression d’une archive. Définissez taille reçue, nombre d’entrées, volume extrait et temps de traitement. Vérifiez le contenu selon l’usage plutôt que le seul suffixe client. Le stockage et la restitution doivent aussi limiter exécution, chemins et accès inter-comptes. Un fichier accepté n’est pas automatiquement sûr dans tout contexte de distribution.
Understand this common mistake
Un type MIME client garantit un fichier sain et petit.
La déclaration ne vérifie ni contenu ni coût.
Distinguer CSRF et XSS
Le CSRF profite notamment de l’envoi automatique d’une identité par le navigateur ; une XSS exécute un script dans un contexte compromis. Un token CSRF ne neutralise pas ce script, et HttpOnly ne supprime pas toutes ses actions. Les protections doivent donc être combinées selon leurs propriétés. Testez une mutation avec token absent, puis un rendu de donnée hostile ; ce sont deux frontières et deux preuves différentes.
Understand this common mistake
Un token CSRF neutralise toute injection de script.
Une XSS peut compromettre le contexte de confiance.
Maîtriser les sorties HTTP serveur
Une URL HTTPS reçue d’un client n’est pas forcément une destination autorisée. Un serveur peut disposer d’accès internes que l’appelant ne devrait pas piloter. Résolvez des partenaires identifiés dans un périmètre maîtrisé et vérifiez redirections, résolution réseau, taille et durée. Une URL initiale correcte ne suffit pas si un saut suivant change le destinataire. Les tests doivent employer un laboratoire et des dépendances simulées.
Understand this common mistake
Toute URL HTTPS reçue est une destination sûre.
Le canal ne rend pas la destination autorisée.
Limiter l’abus sans inventer des droits
Un quota protège une ressource ou un coût selon une fenêtre et des dimensions de comptage. Il ne vérifie pas les permissions sur une réservation. Inversement, un acteur autorisé peut encore épuiser une opération coûteuse. Définissez ces deux décisions séparément et placez la limitation avant l’effet qu’elle veut borner. Un compteur seulement local ne démontre pas une limite globale si plusieurs instances traitent la charge.
Understand this common mistake
Un quota disponible donne des droits métier.
Le budget et l’autorisation sont distincts.
Limiter les conséquences d’un diagnostic
Les logs d’authentification ne doivent pas devenir un stock de tokens, cookies et mots de passe. Des catégories de refus, une version et une corrélation peuvent suffire à l’investigation. Pour un outil CLI, la protection des arguments a aussi plusieurs niveaux : escapeshellarg traite une frontière du shell, mais une valeur commençant par un tiret peut encore devenir une option pour le programme lancé. Préférez une API adaptée et une grammaire d’entrée limitée.
Understand this common mistake
Un log interne peut exposer tous les bearer tokens sans risque.
Une fuite de diagnostic peut créer une capacité d’usurpation.
Atelier guidé : lire, expliquer et vérifier le code
<?php
declare(strict_types=1);
$body = 'document de laboratoire';
$reference = hash('sha256', $body);
echo hash_equals($reference, hash('sha256', $body)) ? 'same' : 'different'; Le programme calcule deux fois une empreinte SHA-256 sur les mêmes octets puis compare les chaînes attendues. La sortie same établit cette égalité dans le petit scénario. Elle ne prouve pas l’auteur du document : aucune référence authentifiée ni clé de signature n’apparaît. Un adversaire capable de remplacer le fichier et la référence publique peut recalculer les deux.
Conservez une référence séparée dans le laboratoire et modifiez un octet du contenu pour observer le refus. Remplacez ensuite les deux valeurs ensemble et notez la limite de cette preuve d’intégrité. Pour une authenticité partagée, étudiez un MAC avec une clé protégée ; pour un droit de lecture, ajoutez une décision d’autorisation. Ces propriétés nécessitent des contrôles distincts même si elles utilisent toutes des chaînes en PHP.
Argument shell délimité et option du programme
Escapeshellarg traite une frontière du shell : il vise à conserver une valeur comme un argument. Le programme lancé interprète ensuite cet argument selon ses propres règles. Un nom commençant par un tiret peut donc être lu comme une option même s’il n’a pas créé un second argument shell.
Préférez une API de bibliothèque lorsqu’elle couvre le besoin. Sinon, évitez le shell avec une API de processus à arguments séparés, validez l’opérande et utilisez le séparateur -- seulement si l’outil le documente. Vérifiez aussi chemin résolu et répertoire autorisé : aucun mécanisme de quoting n’établit un droit sur un fichier.
Dans un laboratoire, remplacez l’outil par un programme qui affiche ses arguments factices, puis vérifiez la commande cible sans effets sensibles. Testez tiret initial, espaces et nom hors périmètre. La preuve recherchée est une interprétation conforme de l’opérande par le programme final, pas simplement une chaîne qui semble correctement entourée de guillemets.
Points de vigilance : TLS protège le transport, mais ne définit pas la grammaire des arguments du programme. L’échappement vise justement la frontière du shell ; l’autre problème est l’interprétation par l’outil. Le scénario ne fait intervenir aucune requête SQL. Un argument correctement délimité peut rester une option dangereuse. Préférer une API, sinon éviter le shell et contrôler les arguments.
Reference documentation ↗UUID et requête préparée : deux protections sans preuve de tenant
Un UUID peut réduire la facilité de deviner une référence. Une requête préparée protège la séparation entre structure SQL et valeurs. Aucun de ces mécanismes ne prouve que la facture trouvée appartient à l’acteur ou à son tenant.
La portée doit venir du contexte authentifié et autorisé côté serveur. Chargez la facture avec les critères de périmètre nécessaires ou appliquez une décision d’objet avant de transmettre son contenu. Un tenantId librement reçu dans la query ne remplace pas cette source de confiance.
Créez deux tenants et une facture de chacun, puis présentez l’UUID valide du premier avec la session du second. Vérifiez absence de corps confidentiel et absence d’effet. Gardez aussi le cas du propriétaire et celui de la ressource absente. Cette matrice distingue l’isolation réelle d’un endpoint qui paraît protégé seulement parce que ses identifiants sont longs ou que son SQL utilise des placeholders.
Points de vigilance : Un identifiant opaque ne remplace pas le contrôle du droit de lecture. Limiter le volume ne rend pas autorisée une seule lecture interdite. La portée doit venir d’un contexte authentifié et autorisé, pas d’un tenantId librement fourni. Une référence peut être connue par de nombreux canaux même si l’interface la masque.
Reference documentation ↗Worked example
<?php
declare(strict_types=1);
$name = '<script>alert(1)</script>';
echo htmlspecialchars($name, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');Le navigateur reçoit une représentation textuelle des caractères spéciaux dans ce contexte HTML. La même fonction ne sécurise pas une requête SQL concaténée.
Practical exercise
Établissez une matrice de tests pour consulter ou annuler une réservation d’un autre utilisateur.
View a suggested solution
Créez deux acteurs et deux ressources. Vérifiez l’autorisation pour lecture et mutation, y compris avec un identifiant deviné. Ajoutez tests CSRF et sorties contenant des caractères HTML.
Verification checklist
- Identifier le contexte exact.
- Ne pas confondre authentification et autorisation.
- Exclure les secrets des logs.
Knowledge check
Related lesson: Sécurité aux frontières de confiance ↗Module validation
101 questions, local practice target of 75%. Suggested duration of 150 minutes, with no enforced deadline. Questions and choices are shuffled; corrections appear after submission. The quick lesson check and the final course exam remain separate exercises.
Start or resume the 101 questions →This records your own progress and does not certify mastery. Complete the exercise before moving on.
