Quelles sont les meilleures pratiques pour éviter les attaques xss sur un site PHP?

J'ai configuré PHP pour que les guillemets magiques soient activés et que les globals s'enregistrent soient désactivés.

je fais de mon mieux pour toujours appeler htmlentities() pour tout ce que je produis qui est dérivé de l'entrée de l'utilisateur.

il m'arrive aussi de saisir ma base de données pour des choses courantes utilisées dans xss attaché tel que...

<script

que dois-je faire d'autre et comment puis-je m'assurer que les choses que j'essaie de faire sont toujours fait.

64
demandé sur Rik Heywood 2008-09-16 15:20:02

20 réponses

échapper à l'entrée n'est pas le meilleur que vous pouvez faire pour la prévention XSS réussie. Aussi la sortie doit être échappée. Si vous utilisez Smarty template engine, vous pouvez utiliser le modificateur |escape:'htmlall' pour convertir tous les caractères sensibles en entités HTML (j'utilise le propre modificateur |e qui est un alias de ce qui précède).

mon approche de la sécurité des entrées / sorties est la suivante:

  • stocker l'entrée de l'utilisateur non modifié (aucun HTML s'échappe sur l'entrée, seulement DB-aware s'échappe fait via AOP prepared statements)
  • échapper à la sortie, selon le format de sortie que vous utilisez (par exemple, HTML et JSON besoin de différents échapper règles)
58
répondu Michał Rudnicki 2008-09-16 11:41:23

je suis d'avis qu'on ne doit rien échapper pendant l'entrée, seulement sur la sortie. Puisque (la plupart du temps) vous ne pouvez pas supposer que vous savez où ces données vont. Par exemple, si vous avez une forme qui prend des données qui apparaissent plus tard dans un courriel que vous envoyez, vous avez besoin d'échapper différent (autrement un utilisateur malveillant pourrait réécrire vos en-têtes de courriel).

en d'autres termes, vous ne pouvez vous échapper qu'au tout dernier moment où les données sont "quitter" votre application:

  • article de la liste
  • Écrire dans un fichier XML, escape for XML
  • Écrire DB, escape (pour le SGBD)
  • Écrire un e-mail, s'échapper pour des e-mails
  • etc

Pour faire court:

  1. vous ne savez pas où vont vos données
  2. Les données
  3. pourraient en fait se retrouver à plus d'un endroit, nécessitant différentes mécanisme d'échappement mais pas les deux
  4. données échappées pour la mauvaise cible n'est vraiment pas agréable. (P. ex. obtenez un e-mail avec le sujet "aller au bar de Tommy".)

Esp #3 se produira si vous échappez des données à la couche d'entrée (ou vous avez besoin de le désamorcer à nouveau, etc).

PS: je suis d'accord avec le Conseil de ne pas utiliser magic_quotes, ce sont des pures diaboliques!

18
répondu Jilles 2008-09-16 21:32:29

il y a beaucoup de façons de faire XSS (voir http://ha.ckers.org/xss.html ) et c'est très difficile à attraper.

je le délègue personnellement au cadre actuel que j'utilise (déclencheur de Code par exemple). Bien que pas parfait, il pourrait attraper plus que ma main fait routines jamais.

12
répondu Christian Studer 2008-09-16 11:38:17

C'est une grande question.

tout d'abord, n'échappez pas au texte à l'entrée, sauf pour le rendre sûr pour le stockage (comme être mis dans une base de données). La raison pour cela est que vous voulez garder ce qui a été input de sorte que vous pouvez le présenter contextuellement de différentes façons et lieux. Faire des changements ici peut compromettre votre présentation ultérieure.

lorsque vous allez présenter vos données filtrer ce qui ne devrait pas être là. Par exemple, s'il n'y a pas de raison pour javascript doit être là le rechercher et de le supprimer. Une façon facile de le faire est d'utiliser la fonction strip_tags et de ne présenter que les balises html que vous autorisez.

Ensuite, prenez ce que vous avez et passez le htmlentities pensé ou htmlspecialchars pour changer ce qui est là en caractères ascii. Faites ceci basé sur le contexte et ce que vous voulez sortir.

je suggère aussi d'éteindre les guillemets magiques. Il a été supprimé de PHP 6 et est considéré comme une mauvaise pratique à utiliser. Détails à http://us3.php.net/magic_quotes

pour plus de détails, voir http://ha.ckers.org/xss.html

Ce n'est pas une réponse complète, mais, espérons-le, assez pour vous aider à obtenir commencé.

10
répondu Matt Farina 2008-09-16 12:13:45

rikh écrit:

je fais de mon mieux pour toujours appeler htmlentities() pour tout ce que je produis qui est dérivé de l'entrée de l'utilisateur.

Voir Joel, son essai sur Rendre le Code Regarde Mal pour aider à cette

7
répondu Mason 2008-09-16 19:13:19

je m'appuie sur PHPTAL pour que.

contrairement à Smarty et plain PHP, il échappe à toute sortie par défaut. C'est une grande victoire pour la sécurité, parce que votre site ne deviendra pas vurnelable si vous oubliez htmlspecialchars() ou |escape quelque part.

XSS est une attaque spécifique au HTML, donc la sortie HTML est le bon endroit pour l'empêcher. Vous ne devriez pas essayer de pré-filtrage des données dans la base de données, parce que vous pourriez avoir besoin de produire des données à un autre médium qui n'accepte pas HTML, mais qui a ses propres risques.

4
répondu Kornel 2009-11-25 21:07:32

la bibliothèque de modèles. ou du moins, c'est ce que les bibliothèques de modèles devraient faire. Pour empêcher XSS tous sortie doit être encodé. Ce n'est pas la tâche de la logique d'application / Commande principale, elle doit être gérée uniquement par les méthodes de sortie.

si vous sprinkle htmlentities() thorughout votre code, la conception globale est erronée. Et comme vous le suggérez, vous pourriez manquer une ou deux taches. C'est pourquoi la seule solution est encodage html rigoureux - > lorsque les variables de sortie sont inscrites dans un flux html/xml.

malheureusement, la plupart des bibliothèques de modèles php n'ajoutent que leur propre syntaxe de modèle, mais ne se préoccupent pas de l'encodage de sortie, ou de la localisation, ou de la validation html, ou quoi que ce soit d'important. Peut-être que quelqu'un d'autre connaît une bibliothèque de templates appropriée pour php?

4
répondu user319490 2010-04-18 02:01:08

échapper à toutes les entrées utilisateur est suffisant pour la plupart des sites. Assurez-vous également que les identifiants de session ne finissent pas dans L'URL afin qu'ils ne puissent pas être volés du lien Referer vers un autre site. En outre, si vous permettez à vos utilisateurs de soumettre des liens, assurez-vous qu'aucun lien de protocole javascript: n'est autorisé; ceux-ci exécuteraient un script dès que l'utilisateur clique sur le lien.

2
répondu Konrad Rudolph 2008-09-16 11:24:39

si vous êtes préoccupé par les attaques XSS, encoder vos chaînes de production en HTML est la solution. Si vous vous souvenez d'encoder chaque caractère de sortie au format HTML, il n'y a aucun moyen d'exécuter une attaque XSS réussie.

lire plus: de la Désinfection des données de l'utilisateur: Comment et où le faire

2
répondu Niyaz 2008-09-16 11:40:58

personnellement, je désactiverais magic_quotes. Dans PHP5+ il est désactivé par défaut et il est préférable de coder comme s'il n'était pas là du tout car il n'échappe pas à tout et il sera supprimé de PHP6.

ensuite, selon le type de données de l'utilisateur que vous filtrez, dictera quoi faire ensuite, par exemple si ce n'est que du texte, par exemple un nom, puis strip_tags(trim(stripslashes())); il ou pour vérifier les plages utiliser des expressions régulières.

si vous attendez une certaine gamme de valeurs, créez un tableau des valeurs valides et n'autorisez ces valeurs qu'à travers ( in_array($userData, array(...)) ).

si vous vérifiez des nombres utilisez is_numeric pour forcer des nombres entiers ou cast à un type spécifique, qui devrait empêcher les gens essayant d'envoyer des chaînes à la place.

si vous avez PHP5.2 + envisagez ensuite de regarder filter () et de faire usage de cette extension qui peut filtrer divers types de données, y compris les adresses e-mail. Documentation n'est pas particulièrement bonne, mais s'améliore.

si vous devez gérer HTML alors vous devriez considérer quelque chose comme filtre D'entrée PHP ou Purificateur HTML . Le purificateur HTML valide également le HTML pour sa conformité. Je ne suis pas sûr que le filtre D'entrée soit encore en cours de développement. Les deux vous permettront de définir un ensemble d'étiquettes qui peuvent être utilisées et quels attributs sont autorisés.

quoi que vous décidiez, toujours rappelez - vous, ne faites jamais confiance à quoi que ce soit venant dans votre script PHP d'un utilisateur (y compris vous-même!).

2
répondu 2008-09-16 19:09:23

toutes ces réponses sont excellentes, mais fondamentalement, la solution à XSS sera d'arrêter de générer des documents HTML par manipulation de chaîne de caractères.

filtrer les entrées est toujours une bonne idée pour n'importe quelle application.

échapper à votre sortie en utilisant htmlentities () et les amis devraient fonctionner aussi longtemps qu'il est utilisé correctement, mais c'est L'équivalent HTML de créer une requête SQL en concaténant des chaînes avec mysql_real_escape_string($var) - il devrait fonctionner, mais moins de choses peuvent valider votre travail, pour ainsi dire, par rapport à une approche comme l'utilisation de requêtes paramétrées.

la solution à long terme devrait être pour les applications de construire la page en interne, peut-être en utilisant une interface standard comme le DOM, et ensuite d'utiliser une bibliothèque (comme libxml) pour gérer la sérialisation vers XHTML/HTML/etc. Bien sûr, nous sommes très loin de celui d'être populaire et assez vite, mais en attendant, nous devons construire nos documents HTML via opérations à la corde, et c'est intrinsèquement plus risqué.

2
répondu Daniel Papasian 2008-09-16 21:24:32

je trouve que l'utilisation de cette fonction Aide à éliminer un grand nombre d'attaques xss possibles: http://www.codebelay.com/killxss.phps

2
répondu barce 2008-09-16 21:35:01

"Magic quotes" est un palliatif remède pour certaines des pires failles XSS qui fonctionne par échapper à tout à l'entrée, quelque chose qui ne va pas, par conception. Le seul cas où l'on voudrait l'utiliser est quand vous devez absolument utiliser une application PHP existante connue pour être écrite négligemment en ce qui concerne XSS. (Dans ce cas, vous êtes dans un sérieux problème, même avec des "guillemets magiques". Lors du développement de votre propre application, vous devriez désactiver "magic quotes" et suivre les pratiques XSS-safe à la place.

XSS, un cross site scripting vulnerability, se produit lorsqu'une application comprend des chaînes à partir de sources externes (la saisie de l'utilisateur, récupérées sur d'autres sites web, etc) dans son [X]HTML, CSS, ECMAscript ou autre navigateur-sortie interprétée sans s'échapper, en espérant que les caractères spéciaux comme des moins-que ([X]HTML), les guillemets simples ou doubles (ECMAscript) n'apparaît jamais. La bonne solution est de toujours échapper aux chaînes selon les règles du langage de sortie: en utilisant les entités dans [X]HTML, les barres obliques inverses dans ECMAscript etc.

parce qu'il peut être difficile de garder une trace de ce qui n'est pas fiable et doit être échappé, c'est une bonne idée de toujours échapper à tout ce qui est une" chaîne de texte "par opposition à" texte avec balisage " dans un langage comme HTML. Certains environnements de programmation le rendent plus facile en introduisant plusieurs types de chaînes incompatibles: "string "(texte normal)," HTML string " (HTML markup) et ainsi de suite. De cette façon, une conversion implicite directe de "string"" "HTML string" serait impossible, et la seule façon qu'une chaîne de caractères puisse devenir un markup HTML est de la passer à travers une fonction d'échappement.

"Register globals", bien que invalidant, c'est certainement une bonne idée, traite d'un problème complètement différent de XSS.

2
répondu Alexey Feldgendler 2010-11-11 15:48:44

faites de vous des cookies de session (ou tous les cookies) que vous utilisez HttpOnly. Dans ce cas, la plupart des navigateurs masquent la valeur du cookie de JavaScript. L'utilisateur peut encore copier manuellement les cookies, mais cela empêche l'accès direct au script. StackOverflow avait ce problème pendant la bêta.

Ce n'est pas une solution, juste une autre brique dans le mur

1
répondu basszero 2008-09-16 12:17:07
  • Ne faites pas confiance à la saisie de l'utilisateur
  • Échapper à tout texte libre sortie
  • N'utilisez pas magic_quotes; voyez s'il y a une variante DBMS-specfic, ou utilisez PDO
  • envisager D'utiliser des cookies HTTP uniquement lorsque cela est possible pour éviter qu'un script malveillant puisse détourner une session
1
répondu Rob 2008-09-16 21:28:06

vous devriez au moins valider toutes les données entrant dans la base de données. Et essayez de valider toutes les données sortant de la base de données.

mysql_real_escape_string est bon pour empêcher L'injection SQL, mais XSS est plus délicat. Vous devriez preg_match, stip_tags, ou htmlentities si possible!

1
répondu Abeon 2010-04-19 23:54:53

la meilleure méthode actuelle pour prévenir XSS dans une application PHP est Purifier HTML (http://htmlpurifier.org/). Un inconvénient mineur est qu'il s'agit d'une bibliothèque assez grande et qu'il est préférable de l'utiliser avec un cache de code op comme APC. Vous l'utiliserez dans n'importe quel endroit où du contenu non fiable est envoyé à l'écran. Il est beaucoup plus complet que htmlentities, htmlspecialchars, filter_input, filter_var, strip_tags, etc.

1
répondu Night Owl 2011-04-24 18:36:55

utiliser une bibliothèque existante d'assainissement des entrées-utilisateurs pour nettoyer toutes les entrées-utilisateurs . À moins que vous ne mettiez un lot d'effort en elle, la mettre en œuvre vous-même ne fonctionnera jamais aussi bien.

0
répondu dbr 2008-09-16 12:04:44

je trouve que le meilleur moyen est d'utiliser une classe qui vous permet de lier votre code afin que vous n'ayez jamais à vous soucier d'échapper manuellement vos données.

0
répondu Darren22 2008-09-16 21:37:34

il est difficile de mettre en œuvre une injection sql/XSS préventive sur un site qui ne cause pas de fausses alarmes. Dans un CMS, l'utilisateur final pourrait vouloir utiliser <script> ou <object> qui renvoie à des éléments d'un autre site.

je recommande à tous les utilisateurs d'Installer FireFox avec NoScript ; -)

-1
répondu Adam 2015-12-17 11:51:31