« Moi, j'échappe juste les guillemets » : pourquoi votre code est vulnérable
\n\nSi vous avez déjà cherché « Comment sanitizer les entrées utilisateur en PHP ? », vous n'êtes pas seul. Cette question sur Stack Overflow cumule des centaines de milliers de vues. Et ce n'est pas étonnant : la sécurité est l'un des sujets les plus brûlants du développement web.
\n\nMais voici le paradoxe : la plupart des réponses à cette question sont soit obsolètes, soit dangereuses. Les développeurs écrivent encore des trucs comme mysql_real_escape_string() (qui n'existe plus depuis 10 ans) ou suppriment simplement les caractères « dangereux ». Spoiler : ça ne marche pas.
Dans cet article, nous allons décortiquer les 5 erreurs les plus fréquentes de sanitisation des entrées utilisateur en PHP qui transforment votre site en passoire, et vous montrer comment les corriger une bonne fois pour toutes.
\n\nErreur n°1 : Croire aveuglément à la « sanitisation » comme solution miracle
\n\nLa plus grosse erreur est de penser qu'il existe une fonction unique capable de « nettoyer » n'importe quelles données. Voici un code typique de débutant :
\n\n<?php\n$name = $_POST['name'];\n$name = strip_tags($name);\n$name = addslashes($name);\n// Les données sont sûres maintenant ? Non !\n?>\n\nLe problème, c'est que chaque contexte nécessite un traitement différent. La validation (vérification du format) et la sanitisation (nettoyage) ne sont pas la même chose. Et il y a aussi l'échappement de sortie, qui se fait à un autre endroit.
\n\nLa bonne approche : Déterminez ce que vous faites avec les données à chaque étape. Pour la base de données, c'est une chose ; pour le HTML, une autre ; pour le JSON, encore une autre.
\n\nErreur n°2 : Utiliser des fonctions obsolètes (ou les appliquer incorrectement)
\n\nPassons en revue les « dinosaures » de la sécurité PHP :
\n\n- \n
mysql_real_escape_string()— supprimée dans PHP 7.0. À oublier. \n addslashes()— ne protège pas contre toutes les injections SQL, surtout avec les encodages multi-octets. \n strip_tags()— supprime les balises, mais n'échappe pas la sortie. Les XSS restent possibles via les attributs. \n
Exemple de code dangereux encore rencontré :
\n\n<?php\n$id = $_GET['id'];\n$id = addslashes($id);\n$query = "SELECT * FROM users WHERE id = '$id'";\n// Si id = 1 OR 1=1 -- vous êtes piraté\n?>\n\nLa bonne approche : Utilisez les requêtes préparées (prepared statements). C'est la seule méthode fiable contre les injections SQL.
\n\n<?php\n$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");\n$stmt->execute(['id' => $_GET['id']]);\n?>\n\nVous voyez ? Pas de sanitisation pour le SQL. Juste des paramètres. La base de données fait elle-même la différence entre une donnée et une commande.
\n\nErreur n°3 : Confondre validation et sanitisation
\n\nBeaucoup pensent : « Je vais supprimer tous les caractères suspects, et ce sera sûr. » Mais cela casse la logique de l'application. Imaginez qu'un utilisateur saisisse le mot de passe P@ssw0rd!, et que vous supprimiez les caractères @ et !. Le mot de passe devient Pssw0rd — et l'utilisateur ne peut plus se connecter.
La validation vérifie si l'entrée correspond au format attendu (email, nombre, URL). Si ce n'est pas le cas, on rejette.
\n\nLa sanitisation supprime ou modifie les caractères indésirables, mais uniquement quand c'est vraiment nécessaire (par exemple, pour un nom de fichier).
\n\nExemple de validation correcte d'un email :
\n\n<?php\n$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);\nif ($email === false) {\n // Email invalide — on ne sauvegarde pas, on n'affiche pas\n echo "Veuillez saisir un email valide";\n exit;\n}\n// Maintenant $email est une chaîne sûre pour tous les usages\n?>\n\nRègle d'or : Si vous attendez un nombre, vérifiez que c'est un nombre. Si c'est un email, vérifiez le format. Tout le reste, rejetez-le.
\n\nErreur n°4 : Ignorer le contexte de sortie (XSS)
\n\nVous avez sauvegardé les données en base via des requêtes préparées. Super, plus d'injections SQL. Mais