web-dev-qa-db-fra.com

Quelles sont les meilleures fonctions de désinfection d'entrée PHP?

J'essaie de créer une fonction que je peux faire passer toutes mes ficelles pour assainir. Ainsi, la chaîne qui en sortira sera sans danger pour l'insertion de base de données. Mais il y en a tellement fonctions de filtrage Je ne suis pas sûr de celles que je devrais utiliser/dont j'ai besoin.

S'il vous plaît aidez-moi à remplir les blancs:

function filterThis($string) {
    $string = mysql_real_escape_string($string);
    $string = htmlentities($string);
    etc...
    return $string;
}
156
Lauren

Arrêtez!

Vous faites une erreur ici. Oh, non, vous avez sélectionné les bonnes fonctions PHP pour rendre vos données un peu plus sûres. C'est très bien. Votre erreur est dans l'ordre des opérations , et comment et où utiliser ces fonctions.

Il est important de comprendre la différence entre la purification et la validation des données utilisateur, l'échappement de données pour le stockage et l'échappement de données pour la présentation.

Désinfection et validation des données utilisateur

Lorsque les utilisateurs soumettent des données, vous devez vous assurer qu'ils ont fourni les informations attendues.

Assainissement et Filtrage

Par exemple, si vous attendez un nombre , assurez-vous que les données soumises sont un nombre . Vous pouvez également convertir les données utilisateur dans d'autres types. Tout ce qui est soumis est initialement traité comme une chaîne. Par conséquent, le fait de forcer des données numériques connues à devenir un entier ou un flottant rend la désinfection rapide et sans douleur.

Qu'en est-il des champs de texte libre et des zones de texte? Vous devez vous assurer qu'il n'y a rien d'inattendu dans ces domaines. En règle générale, vous devez vous assurer que les champs ne contenant aucun contenu HTML ne contiennent pas réellement HTML. Vous pouvez résoudre ce problème de deux manières.

Tout d’abord, vous pouvez essayer d’échapper l’entrée HTML avec htmlspecialchars . Vous ne devez pas utiliser htmlentities pour neutraliser le code HTML, car celui-ci encodera également les caractères accentués et les autres caractères qui, à son avis, doivent également l'être.

Deuxièmement, vous pouvez essayer de supprimer tout code HTML possible. strip_tags est rapide et facile, mais aussi bâclé. HTML Purifier effectue un travail beaucoup plus approfondi en supprimant tout le code HTML et en permettant également une liste blanche sélective de balises et d'attributs.

Les versions modernes de PHP sont livrées avec l'extension de filtre , qui fournit un moyen complet de nettoyer les entrées utilisateur.

Validation

S'assurer que les données soumises sont exemptes de contenu inattendu ne représente que la moitié du travail. Vous devez également essayer de vous assurer que les données soumises contiennent des valeurs avec lesquelles vous pouvez réellement travailler.

Si vous attendez un nombre compris entre 1 et 10, vous devez vérifier cette valeur. Si vous utilisez l'une de ces nouvelles entrées numériques de l'ère HTML5 avec une flèche et des étapes, assurez-vous que les données soumises sont conformes à l'étape.

Si ces données proviennent d'un menu déroulant, assurez-vous que la valeur soumise est celle qui apparaît dans le menu.

Qu'en est-il des entrées de texte qui répondent à d'autres besoins? Par exemple, les entrées de date doivent être validées via strtotime ou la classe DateTime . La date donnée doit se situer entre les plages que vous attendez. Qu'en est-il des adresses e-mail? L'extension de filtre mentionnée précédemment peut vérifier qu'une adresse est correctement formée, bien que je sois fan de de la bibliothèque is_email .

Il en va de même pour tous les autres contrôles de formulaire. Avoir des boutons radio? Validez contre la liste. Ont des cases à cocher? Validez contre la liste. Vous avez un fichier à télécharger? Assurez-vous que le fichier est d'un type attendu et traitez le nom de fichier comme des données utilisateur non filtrées.

Chaque navigateur moderne est livré avec un ensemble complet d'outils de développement intégrés, ce qui le rend simple pour quiconque de manipuler votre formulaire. Votre code doit supposer que l'utilisateur a complètement supprimé toutes les restrictions côté client sur le contenu du formulaire !

Échappement des données pour le stockage

Maintenant que vous vous êtes assuré que vos données sont dans le format prévu et ne contiennent que les valeurs attendues, vous devez vous inquiéter de la conservation de ces données dans un stockage.

Chaque mécanisme de stockage de données possède un moyen spécifique de s’assurer que les données sont correctement échappées et codées. Si vous générez du SQL, le moyen accepté de transmettre des données dans des requêtes consiste à utiliser des instructions préparées avec des espaces réservés .

L’un des meilleurs moyens de travailler avec la plupart des bases de données SQL dans PHP est l’extension PDO . Il suit le modèle commun de préparer une instruction , lier des variables à l'instruction , puis envoyer l'instruction et les variables au serveur. . Si vous n'avez pas encore utilisé PDO , voici un très bon tutoriel orienté MySQL .

Certaines bases de données SQL ont leurs propres extensions spécialisées en PHP, notamment SQL Server , PostgreSQL et SQLite 3 . Chacune de ces extensions a un support d'instructions préparées qui fonctionne de la même façon que préparer-lier-exécuter que PDO. Parfois, vous devrez peut-être utiliser ces extensions au lieu de PDO pour prendre en charge des fonctionnalités ou des comportements non standard.

MySQL possède également ses propres extensions PHP. Deux d'entre eux, en fait. Vous voulez seulement utiliser celui qui s'appelle mysqli . L'ancienne extension "mysql" a été obsolète et n'est pas sûre ni saine d'utilisation à l'ère moderne.

Personnellement, je ne suis pas un fan de mysqli. La façon dont il effectue la liaison variable sur les instructions préparées est inflexible et peut être pénible à utiliser. En cas de doute, utilisez plutôt PDO.

Si vous n'utilisez pas de base de données SQL pour stocker vos données, consultez la documentation de l'interface de base de données utilisée pour déterminer comment transférer en toute sécurité des données.

Lorsque cela est possible, assurez-vous que votre base de données stocke vos données dans un format approprié. Stocker des nombres dans des champs numériques. Stocker les dates dans les champs de date. Stocker de l'argent dans un champ décimal, pas un champ à virgule flottante. Consultez la documentation fournie par votre base de données pour savoir comment stocker correctement différents types de données.

Échappement de données pour présentation

Chaque fois que vous montrez des données à des utilisateurs, vous devez vous assurer que les données sont échappées en toute sécurité, à moins que vous sachiez qu'il ne devrait pas être échappé.

Lorsque vous émettez du HTML, vous devez presque toujours transmettre les données fournies à l'origine par l'utilisateur via htmlspecialchars . En fait, la seule fois où vous ne devriez pas faire cela, c’est lorsque vous savez que l’utilisateur a fourni le code HTML et que vous savez qu'il a déjà été nettoyé à l'aide d'une liste blanche.

Parfois, vous devez générer du Javascript avec PHP. Javascript n'a pas les mêmes règles d'échappement que le HTML! Un moyen sûr de fournir à Javascript des valeurs fournies par l'utilisateur via PHP consiste à utiliser json_encode .

Et plus

La validation des données comporte beaucoup plus de nuances.

Par exemple, le codage de jeux de caractères peut être un piège énorme . Votre application doit suivre les pratiques décrites dans " UTF-8 tout au long de ". Des attaques hypothétiques peuvent survenir lorsque vous traitez des données de chaîne comme un jeu de caractères incorrect.

J'ai mentionné précédemment des outils de débogage de navigateur. Ces outils peuvent également être utilisés pour manipuler les données de cookies. Les cookies doivent être traités comme des entrées non fiables .

La validation et l'échappement de données ne sont qu'un aspect de la sécurité des applications Web. Vous devez vous familiariser avec les méthodologies d'attaque d'applications Web afin de pouvoir créer des défenses contre celles-ci.

417
Charles

La désinfection la plus efficace pour empêcher l’injection SQL est le paramétrage à l’aide de PDO. À l'aide de requêtes paramétrées, la requête est séparée des données, ce qui supprime le risque d'injection SQL de premier ordre.

En termes de suppression de HTML, strip_tags est probablement la meilleure idée pour supprimer HTML, car elle supprime simplement tout. htmlentities fait ce que cela ressemble, de sorte que cela fonctionne aussi. Si vous devez analyser quel code HTML autoriser (c'est-à-dire, vous souhaitez autoriser certaines balises ), vous devez utiliser un analyseur syntaxique existant, tel que - purificateur HTML

31
Derek H

Entrée de base de données - Comment empêcher l'injection SQL

  1. Assurez-vous, par exemple, que les données de type entier sont valides en vérifiant qu’il s’agit bien d’un entier
    • Dans le cas de non-chaînes, vous devez vous assurer que le type de données est correct.
    • Dans le cas de chaînes, vous devez vous assurer que la chaîne est entourée de guillemets dans la requête (évidemment, sinon cela ne fonctionnerait même pas)
  2. Entrez la valeur dans la base de données en évitant l’injection SQL (mysql_real_escape_string ou requêtes paramétrées)
  3. Lors de la récupération de la valeur de la base de données, évitez les attaques de type Cross Site Scripting en vous assurant que le code HTML ne peut pas être injecté dans la page (htmlspecialchars).

Vous devez échapper à la saisie de l'utilisateur avant de l'insérer ou de la mettre à jour dans la base de données. Voici une façon plus ancienne de le faire. Vous voudriez maintenant utiliser des requêtes paramétrées (probablement de la classe PDO).

$mysql['username'] = mysql_real_escape_string($clean['username']);
$sql = "SELECT * FROM userlist WHERE username = '{$mysql['username']}'";
$result = mysql_query($sql);

Sortie de la base de données - Comment empêcher XSS (Cross Site Scripting)

Utilisez htmlspecialchars() uniquement lors de la sortie de données de la base de données. La même chose s'applique pour HTML Purifier. Exemple:

$html['username'] = htmlspecialchars($clean['username'])

Et enfin ... ce que vous avez demandé

Je dois souligner que si vous utilisez des objets PDO avec des requêtes paramétrées (la bonne façon de le faire), il n’existe vraiment aucun moyen simple d’y parvenir facilement. Mais si vous utilisez l'ancienne méthode 'mysql', c'est ce dont vous auriez besoin.

function filterThis($string) {
    return mysql_real_escape_string($string);
}
11
Joe Phillips

Mes 5 centimes.

Personne ici ne comprend le fonctionnement de mysql_real_escape_string. Cette fonction ne filtre ni ne "désinfecte" quoi que ce soit.
Vous ne pouvez donc pas utiliser cette fonction comme un filtre universel qui vous évitera l’injection.
Vous ne pouvez l’utiliser que si vous comprenez comment fonctionne l’application et où elle s’applique.

J'ai la réponse à la question très similaire que j'ai déjà écrite: Dans PHP lorsque je soumets des chaînes à la base de données, dois-je m'occuper des caractères illégaux à l'aide de htmlspecialchars () ou utiliser une expression régulière? =
Veuillez cliquer ici pour une explication complète de la sécurité côté base de données.

En ce qui concerne les idées, Charles a raison de vous dire de séparer ces fonctions.
Imaginez que vous allez insérer des données, générées par admin, qui sont autorisées à publier du code HTML. votre fonction va le gâcher.

Bien que je déconseille htmlentities. Cette fonction devient obsolète depuis longtemps. Si vous souhaitez remplacer uniquement les caractères <, > et " par souci de sécurité HTML, utilisez la fonction développée à cet effet intentionnellement - un htmlspecialchars () un.

5
Your Common Sense

Cela dépend du type de données que vous utilisez. Le mieux à utiliser en général serait mysqli_real_escape_string mais, par exemple, vous savez qu'il n'y aura pas de contenu HTML, utiliser strip_tags ajoutera une sécurité supplémentaire.

Vous pouvez également supprimer des personnages dont vous savez qu'ils ne devraient pas être autorisés.

2
Aaron Harun

Pour l'insertion de base de données, tout ce dont vous avez besoin est mysql_real_escape_string (ou utilisez des requêtes paramétrées). Généralement, vous ne voulez pas modifier les données avant de les enregistrer, ce qui se produirait si vous utilisiez htmlentities. Cela conduirait à un désordre déformé plus tard, lorsque vous l'exécuterez à nouveau htmlentities pour l'afficher quelque part sur une page Web.

Utilisez htmlentities lorsque vous affichez les données sur une page Web quelque part.

En quelque sorte, si vous envoyez des données soumises quelque part dans un e-mail, comme avec un formulaire de contact par exemple, veillez à supprimer les nouvelles lignes de toutes les données qui seront utilisées dans l'en-tête (comme le De: nom et adresse e-mail, etc.). )

$input = preg_replace('/\s+/', ' ', $input);

Si vous ne le faites pas, ce n'est qu'une question de temps avant que les robots collecteurs de spam trouvent votre formulaire et en abusent, j'ai appris à la dure.

2
Rob
2
T.Todua

Je recommande toujours d'utiliser un petit paquet de validation comme GUMP: https://github.com/Wixel/GUMP

Construisez toutes vos fonctions de base autour d'une bibliothèque comme celle-ci et il est presque impossible d'oublier les installations sanitaires. "mysql_real_escape_string" n'est pas la meilleure alternative pour un bon filtrage (comme l'explique "Votre sens commun") - et si vous oubliez de l'utiliser une seule fois, tout votre système sera attaquable par injections et autres assauts méchants.

1
Simon Schneider

Pour tous ceux qui parlent ici et qui s'appuient sur mysql_real_escape_string, vous devez noter que cette fonction est obsolète sur PHP5 et n'existe plus sur PHP7.

IMHO le meilleur moyen d'accomplir cette tâche est d'utiliser des requêtes paramétrées via PDO pour interagir avec la base de données. Vérifiez ceci: https://phpdelusions.net/pdo_examples/select

Utilisez toujours des filtres pour traiter les entrées de l'utilisateur. Voir http://php.net/manual/es/function.filter-input.php

1
Kuntur

Vous utilisez mysql_real_escape_string () dans un code similaire au suivant.

$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
  mysql_real_escape_string($user),
  mysql_real_escape_string($password)
);

Comme le dit la documentation, son but est d'échapper aux caractères spéciaux de la chaîne passée en argument, en prenant en compte le jeu de caractères actuel de la connexion, de sorte qu'il est prudent de la placer dans un mysql_query () . La documentation ajoute également:

Si des données binaires doivent être insérées, cette fonction doit être utilisée.

htmlentities () est utilisé pour convertir certains caractères en entités, lorsque vous exportez une chaîne au contenu HTML.

0
kiamlaluno