Existe-t-il une fonction catchall quelque part qui fonctionne bien pour nettoyer les entrées utilisateur pour l'injection SQL et les attaques XSS, tout en autorisant certains types de balises HTML?
1124
Existe-t-il une fonction catchall quelque part qui fonctionne bien pour nettoyer les entrées utilisateur pour l'injection SQL et les attaques XSS, tout en autorisant certains types de balises HTML?
select * from users where name='$name'
, alors peu importe si vous utilisez PDO ou MySQLi ou MySQL. Tu es toujours en danger. Vous devez utiliser des requêtes paramétrées ou, si vous devez, utiliser des mécanismes d'échappement sur vos données, mais c'est beaucoup moins préférable.Réponses:
C'est une idée fausse commune que l'entrée d'utilisateur peut être filtrée. PHP a même une "fonctionnalité" (désormais obsolète), appelée magic-quotes , qui s'appuie sur cette idée. C'est n'importe quoi. Oubliez le filtrage (ou le nettoyage, ou ce que les gens appellent).
Ce que vous devez faire, pour éviter les problèmes, est assez simple: chaque fois que vous intégrez une chaîne dans un code étranger, vous devez y échapper, selon les règles de cette langue. Par exemple, si vous intégrez une chaîne dans du SQL ciblant MySQL, vous devez échapper la chaîne avec la fonction MySQL à cet effet (
mysqli_real_escape_string
). (Ou, dans le cas de bases de données, l'utilisation de déclarations préparées est une meilleure approche, si possible.)Un autre exemple est HTML: si vous incorporez des chaînes dans le balisage HTML, vous devez l'échapper avec
htmlspecialchars
. Cela signifie que chaque singleecho
ouprint
instruction doit utiliserhtmlspecialchars
.Un troisième exemple pourrait être les commandes shell: si vous allez incorporer des chaînes (telles que des arguments) à des commandes externes et les appeler avec
exec
, vous devez utiliserescapeshellcmd
etescapeshellarg
.Et ainsi de suite ...
Le seul cas où vous devez filtrer activement les données, c'est si vous acceptez une entrée préformatée. Par exemple, si vous autorisez vos utilisateurs à publier du balisage HTML, que vous prévoyez d'afficher sur le site. Cependant, vous devriez être prudent pour éviter cela à tout prix, car peu importe la façon dont vous le filtrez, ce sera toujours un trou de sécurité potentiel.
la source
mysql_real_escape_string
est obsolète. Il est de nos jours considéré comme une bonne pratique d'utiliser des instructions préparées pour empêcher l'injection SQL. Passez donc à MySQLi ou PDO.N'essayez pas d'empêcher l'injection SQL en filtrant les données d'entrée.
Au lieu de cela, n'autorisez pas les données à utiliser dans la création de votre code SQL . Utilisez des instructions préparées (c'est-à-dire en utilisant des paramètres dans une requête de modèle) qui utilisent des variables liées. C'est le seul moyen d'être garanti contre l'injection SQL.
Veuillez consulter mon site Web http://bobby-tables.com/ pour en savoir plus sur la prévention de l'injection SQL.
la source
Non. Vous ne pouvez pas filtrer les données de manière générique sans aucun contexte de leur utilisation. Parfois, vous voudriez prendre une requête SQL en entrée et parfois vous voudriez prendre HTML en entrée.
Vous devez filtrer les entrées sur une liste blanche - assurez-vous que les données correspondent à certaines spécifications de ce que vous attendez. Ensuite, vous devez y échapper avant de l'utiliser, selon le contexte dans lequel vous l'utilisez.
Le processus d'échappement des données pour SQL - pour empêcher l'injection SQL - est très différent du processus d'échappement des données pour (X) HTML, pour empêcher XSS.
la source
PHP a maintenant les nouvelles fonctions sympas de filter_input, qui par exemple vous libèrent de trouver 'l'ultime regex de messagerie' maintenant qu'il y a un type FILTER_VALIDATE_EMAIL intégré
Ma propre classe de filtre (utilise JavaScript pour mettre en évidence les champs défectueux) peut être lancée soit par une demande ajax, soit par un post de formulaire normal. (voir l'exemple ci-dessous)
Bien sûr, gardez à l'esprit que vous devez également échapper votre requête SQL en fonction du type de base de données que vous utilisez (mysql_real_escape_string () est inutile pour un serveur SQL par exemple). Vous souhaiterez probablement gérer cela automatiquement au niveau de votre couche d'application appropriée, comme un ORM. Aussi, comme mentionné ci-dessus: pour la sortie en html, utilisez les autres fonctions dédiées à php comme htmlspecialchars;)
Pour vraiment autoriser l'entrée HTML avec des classes et / ou balises supprimées, dépendez de l'un des packages de validation xss dédiés. N'ÉCRIVEZ PAS VOS PROPRES REGEXES POUR ANALYSER LE HTML!
la source
Non, il n'y en a pas.
Tout d'abord, l'injection SQL est un problème de filtrage des entrées, et XSS est une sortie qui échappe à un - donc vous ne pourriez même pas exécuter ces deux opérations en même temps dans le cycle de vie du code.
Règles de base
mysql_real_escape_string()
)strip_tags()
pour filtrer le HTML indésirablehtmlspecialchars()
et faites attention aux 2e et 3e paramètres ici.la source
Pour résoudre le problème XSS, jetez un œil à HTML Purifier . Il est assez configurable et a une expérience professionnelle décente.
En ce qui concerne les attaques par injection SQL, assurez-vous de vérifier l'entrée utilisateur, puis exécutez-la via mysql_real_escape_string (). Cependant, la fonction ne vaincra pas toutes les attaques par injection, il est donc important de vérifier les données avant de les vider dans votre chaîne de requête.
Une meilleure solution consiste à utiliser des instructions préparées. La bibliothèque PDO et l'extension mysqli les prennent en charge.
la source
PHP 5.2 a introduit la fonction filter_var .
Il prend en charge de nombreux filtres SANITIZE, VALIDATE.
http://php.net/manual/en/function.filter-var.php
la source
Une astuce qui peut aider dans le cas spécifique où vous avez une page comme
/mypage?id=53
et que vous utilisez l'id dans une clause WHERE est de vous assurer que l'id est définitivement un entier, comme ceci:Mais bien sûr, cela ne coupe qu'une seule attaque spécifique, alors lisez toutes les autres réponses. (Et oui, je sais que le code ci-dessus n'est pas génial, mais il montre la défense spécifique.)
la source
$id = (int)$_GET['id']
et$que = sprintf('SELECT ... WHERE id="%d"', $id)
c'est bien aussiUtilisez des versions modernes de MySQL et PHP.
Définissez explicitement le jeu de caractères:
Utilisez des jeux de caractères sécurisés:
Utiliser la fonction spatialisée:
PDO :: quote () - place des guillemets autour de la chaîne d'entrée (si nécessaire) et échappe les caractères spéciaux dans la chaîne d'entrée, en utilisant un style de guillemets approprié au pilote sous-jacent:
Instructions préparées par PDO : vs les instructions préparées par MySQLi prennent en charge davantage de pilotes de base de données et de paramètres nommés:
mysql_real_escape_string[déconseillé en PHP 5.5.0, supprimé en PHP 7.0.0].Vérifiez que la variable contient ce que vous attendez:
Utiliser la fonction de filtre filter_var () - filtre une variable avec un filtre spécifié:
filtres plus prédéfinis
la source
Vous décrivez ici deux problèmes distincts:
1) L'entrée utilisateur doit toujours être considérée comme mauvaise.
Utiliser des instructions préparées ou / et filtrer avec mysql_real_escape_string est définitivement un must. PHP a également intégré filter_input, ce qui est un bon point de départ.
2) Il s'agit d'un grand sujet qui dépend du contexte des données en cours de sortie. Pour HTML, il existe des solutions telles que htmlpurifier. en règle générale, échappez toujours à tout ce que vous produisez.
Les deux problèmes sont beaucoup trop importants pour être abordés dans un seul article, mais il existe de nombreux articles plus détaillés:
Méthodes de sortie PHP
Sortie PHP plus sûre
la source
Si vous utilisez PostgreSQL, l'entrée de PHP peut être échappée avec pg_escape_string ()
Depuis la documentation ( http://php.net/manual/es/function.pg-escape-string.php ):
la source
Il n'y a pas de fonction de fourre-tout, car il existe de multiples préoccupations à résoudre.
Injection SQL - Aujourd'hui, généralement, chaque projet PHP devrait utiliser des instructions préparées via PHP Data Objects (PDO) comme meilleure pratique, empêchant une erreur d'une citation erronée ainsi qu'une solution complète contre l'injection . C'est également le moyen le plus flexible et le plus sécurisé d'accéder à votre base de données.
Consultez (le seul bon) tutoriel PDO pour à peu près tout ce que vous devez savoir sur PDO. (Merci sincèrement au principal contributeur SO, @YourCommonSense, pour cette excellente ressource sur le sujet.)
XSS - Assainissez les données en chemin ...
HTML Purifier existe depuis longtemps et est toujours activement mis à jour. Vous pouvez l'utiliser pour nettoyer les entrées malveillantes, tout en permettant une liste blanche généreuse et configurable de balises. Fonctionne très bien avec de nombreux éditeurs WYSIWYG, mais il peut être lourd pour certains cas d'utilisation.
Dans d'autres cas, où nous ne voulons pas du tout accepter HTML / Javascript, j'ai trouvé cette fonction simple utile (et j'ai passé plusieurs audits contre XSS):
/* Prevent XSS input */ function sanitizeXSS () { $_GET = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING); $_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING); $_REQUEST = (array)$_POST + (array)$_GET + (array)$_REQUEST; }
XSS - Assainir les données à la sortie ... à moins que vous ne garantissiez que les données ont été correctement assainies avant de les ajouter à votre base de données, vous devrez les assainir avant de les afficher à votre utilisateur, nous pouvons tirer parti de ces fonctions PHP utiles:
echo
ouprint
pour afficher des valeurs fournies par l'utilisateur, utilisez-leshtmlspecialchars
sauf si les données ont été correctement nettoyées en toute sécurité et sont autorisées à afficher du HTML.json_encode
est un moyen sûr de fournir des valeurs fournies par l'utilisateur de PHP à JavascriptAppelez-vous des commandes shell externes à l' aide
exec()
ou dessystem()
fonctions, ou à l'backtick
opérateur? Si c'est le cas, en plus de SQL Injection & XSS, vous pourriez avoir une préoccupation supplémentaire à résoudre, les utilisateurs exécutant des commandes malveillantes sur votre serveur . Vous devez utiliserescapeshellcmd
si vous souhaitez échapper à la commande entière OUescapeshellarg
pour échapper aux arguments individuels.la source
mb_encode_numericentity
est discuté dans lehtmlspecialchars
lien sur # 3 XSSLe moyen le plus simple d'éviter les erreurs de nettoyage des données d'entrée et d'échappement est d'utiliser un framework PHP comme Symfony , Nette etc. ou une partie de ce framework (moteur de template, couche de base de données, ORM).
Le moteur de modèle comme Twig ou Latte a un échappement de sortie par défaut - vous n'avez pas à résoudre manuellement si vous avez correctement échappé votre sortie en fonction du contexte (partie HTML ou Javascript de la page Web).
Le framework nettoie automatiquement les entrées et vous ne devez pas utiliser directement les variables $ _POST, $ _GET ou $ _SESSION, mais par le biais de mécanismes comme le routage, la gestion des sessions, etc.
Et pour la couche de base de données (modèle), il existe des cadres ORM comme Doctrine ou des wrappers autour de PDO comme Nette Database.
Vous pouvez en savoir plus ici - Qu'est - ce qu'un framework logiciel?
la source
Je voulais juste ajouter qu'au sujet de l'échappement de sortie, si vous utilisez php DOMDocument pour faire votre sortie html, il s'échappera automatiquement dans le bon contexte. Un attribut (valeur = "") et le texte interne d'un <span> ne sont pas égaux. Pour être sûr contre XSS, lisez ceci: OWASP XSS Prevention Cheat Sheet
la source
Vous ne désinfectez jamais l'entrée.
Vous désinfectez toujours la sortie.
Les transformations que vous appliquez aux données pour garantir leur inclusion dans une instruction SQL sont complètement différentes de celles que vous demandez pour l'inclusion dans HTML sont complètement différentes de celles que vous demandez pour l'inclusion dans Javascript sont complètement différentes de celles que vous demandez pour l'inclusion dans LDIF sont complètement différents de ceux que vous appliquez à l'inclusion dans CSS sont complètement différents de ceux que vous appliquez à l'inclusion dans un e-mail ....
Validez par tous les moyens l' entrée - décidez si vous devez l'accepter pour un traitement ultérieur ou dites à l'utilisateur qu'elle est inacceptable. Mais n'appliquez aucune modification à la représentation des données avant qu'elles ne quittent PHP Land.
Il y a longtemps, quelqu'un a essayé d'inventer un mécanisme unique pour échapper aux données et nous nous sommes retrouvés avec " magic_quotes " qui n'échappait pas correctement les données pour toutes les cibles de sortie et entraînait une installation différente nécessitant un code différent pour fonctionner.
la source
Ne faites jamais confiance aux données utilisateur.
La
trim()
fonction supprime les espaces et autres caractères prédéfinis des deux côtés d'une chaîne.La
stripslashes()
fonction supprime les contre-obliquesLa
htmlspecialchars()
fonction convertit certains caractères prédéfinis en entités HTML.Les caractères prédéfinis sont:
la source
clean_input
alors? Pourquoi voudriez-vous supprimer les barres obliques?Il y a l'extension de filtre ( howto-link , manuel ), qui fonctionne assez bien avec toutes les variables GPC. Ce n'est pas une chose magique, cependant, vous devrez toujours l'utiliser.
la source