web-dev-qa-db-fra.com

Assainissement des données utilisateur dans GET par PHP

Comment nettoyez-vous les données dans les variables $ _GET par PHP?

Je désinfecte une seule variable dans GET par strip_tags. Je ne sais pas si je devrais tout nettoyer ou non, car la dernière fois que j'ai mis des données à Postgres, le problème a été résolu le plus facilement par l'utilisation de pg_prepare.

Comment nettoyer les données dans les variables $ _GET par PHP?

Vous ne nettoyez pas les données dans $ _GET. C'est une approche courante dans les scripts PHP, mais c'est complètement faux *.

Toutes vos variables doivent rester sous forme de texte brut jusqu'au moment où vous les intégrez dans un autre type de chaîne. Il n’existe aucune forme d’échappement ou de "désinfection" qui puisse couvrir tous les types de chaînes possibles dans lesquels vous pourriez incorporer vos valeurs.

Donc, si vous incorporez une chaîne dans une requête SQL, vous devez l'échapper à la sortie:

$sql= "SELECT * FROM accounts WHERE username='".pg_escape_string($_GET['username'])."'";

Et si vous crachez la chaîne en HTML, vous devez l'échapper alors:

Cannot log in as <?php echo(htmlspecialchars($_GET['username'], ENT_QUOTES)) ?>.

Si vous avez effectué ces deux étapes d'échappement sur le tableau $ _GET au début, comme recommandé par les personnes qui ne savent pas ce qu'elles font:

$_GET['username']= htmlspecialchars(pg_escape_string($_GET['username']));

Ensuite, lorsque vous aviez un ‘’ dans votre nom d’utilisateur, il se transformerait mystérieusement en ‘amp;’ dans votre base de données, et si vous aviez une apostrophe dans votre nom d’utilisateur, elle se transformerait en deux apostrophes sur la page. Ensuite, lorsque vous avez un formulaire contenant ces caractères, il est facile de finir par des choses à double échappement lorsqu'ils sont modifiés, c'est pourquoi tant de mauvais PHP CMS se retrouvent avec des titres d'articles cassés comme "Nouveaux livres d'O \\\\\\\\\\\\\\\\\\\ 'Reilly".

Naturellement, se souvenir de pg_escape_string ou mysql_real_escape_string et htmlspecialchars chaque fois que vous envoyez une variable est un peu fastidieux, c'est pourquoi tout le monde veut le faire (incorrectement) au même endroit au début du script. Pour la sortie HTML, vous pouvez au moins enregistrer certaines saisies en définissant une fonction avec un nom court qui fait écho (htmlspecialchars (...)).

Pour SQL, il vaut mieux utiliser des requêtes paramétrées. Pour Postgres, il y a pg_query_params . Ou bien, préparé des déclarations comme vous l'avez mentionné (bien que personnellement je les trouve moins gérables). Dans les deux cas, vous pouvez ensuite oublier la "désinfection" ou l'échappement pour SQL, mais vous devez toujours vous échapper si vous intégrez d'autres types de chaînes, y compris HTML.

strip_tags () n'est pas un bon moyen de traiter les entrées pour l'affichage HTML. Dans le passé, il a eu des problèmes de sécurité, car les analyseurs de navigateur sont en réalité beaucoup plus compliqués dans leur interprétation de ce qu'une balise peut être que vous ne le pensez. htmlspecialchars () est presque toujours la bonne chose à utiliser à la place, de sorte que si quelqu'un tape un signe inférieur à, il obtiendra un signe inférieur à littéral et ne trouvera pas la moitié de son texte disparaissant mystérieusement.

(*: comme une approche générale pour résoudre les problèmes d'injection, de toute façon. Naturellement, il y a des vérifications spécifiques au domaine qu'il vaut la peine de faire sur des champs particuliers, et il y a des tâches de nettoyage utiles que vous pouvez faire comme supprimer tous les caractères de contrôle des valeurs soumises. Mais c'est pas ce que la plupart PHP entendent par désinfection.)

77
bobince

Si vous parlez de filtrer la sortie, je recommanderais de stocker le contenu dans votre base de données sous sa forme complète et non échappée, puis de l'échapper ( htmlspecialchars ou quelque chose) lorsque vous faites écho aux données, de cette façon vous avez plus d'options pour la sortie. Voir this question pour une discussion sur le nettoyage/échappement du contenu de la base de données.

En termes de stockage dans postgres, utilisez pg_escape_string sur chaque variable de la requête, pour échapper aux guillemets et protéger généralement contre l'injection SQL.

Éditer:

Mes étapes habituelles pour stocker des données dans une base de données, puis les récupérer, sont les suivantes:

  1. Appelez la fonction d'échappement des données de la base de données (pg_escape_string, mysql_escape_string, etc.) pour échapper à chaque variable $ _GET entrante utilisée dans votre requête. Notez que l'utilisation de ces fonctions au lieu d'ajouts de barres obliques entraîne l'absence de barres obliques supplémentaires dans le texte lorsqu'il est stocké dans la base de données.

  2. Lorsque vous récupérez les données de la base de données, vous pouvez simplement utiliser htmlspecialchars sur toutes les données générées, pas besoin d'utiliser des barres obliques, car il ne devrait pas y avoir de barres obliques supplémentaires.

5
Kazar

Vous devez nettoyer toutes les demandes, pas seulement POST as GET.

Vous pouvez utiliser la fonction htmlentities () , la fonction preg_replace () avec regex, ou filtrer par transtypage:

<?
$id = (int)$_GET['id'];
?>

[]

3
fvox

Désinfectez vos entrées en fonction de leur destination.

  • Si vous l'affichez (sur une page ou comme valeur d'un champ de saisie), utilisez htmlspecialchars et/ou str_replace.
  • Si vous l'utilisez comme un autre type, lancez-le.
  • Si vous l'incluez dans la requête SQL, échappez-la à l'aide de la fonction appropriée, supprimez peut-être les balises html si vous souhaitez que celles-ci soient totalement supprimées (ce qui n'est pas la même chose que d'échappement).

Idem pour POST ou même des données de votre base de données, car les données à l'intérieur de votre base de données ne doivent généralement pas être échappées.

Deux choses à vérifier:

  1. Encodage de votre entrée par rapport à votre PHP scripts/sortie/table DB
  2. Si [magic_quotes_gpc][1] Est activé, vous devez le désactiver (chaque fois que vous le pouvez) ou stripslashes() GET, POST et valeurs COOKIE. magic_quotes_gpc est obsolète, vous devez nettoyer les données que vous manipulez, en fonction de tiliser de ces données.
2
instanceof me