web-dev-qa-db-fra.com

Quels sont les concepts importants à enseigner aux développeurs sur les scripts intersites (XSS)?

J'aide avec une formation d'une heure pour les développeurs (~ 100 d'entre eux) sur les scripts intersites. Quels sont, selon vous, les concepts indispensables pour leur transmettre? En ce moment, nous avons:

  • Différence entre réfléchi et stocké
  • Couches de défense ( WAF , défenses du navigateur, en-têtes de serveur et codage sécurisé)
  • Codage sécurisé et contexte des paramètres de codage

Et surtout, l'impact potentiel des vulnérabilités.

41
mcgyver5

Du point de vue d'un développeur, les deux premiers points que vous avez ne sont pas très pertinents. Les XSS stockés et réfléchis ont la même atténuation: échappent correctement les éléments que vous générez en fonction de leur contexte. Les couches de défense ne seront probablement perçues que comme une excuse pour mal mettre en œuvre cette atténuation: "Le WAF va l'attraper pour moi."

Au lieu de cela, concentrez-vous sur ces pratiques d'hygiène du code:

  • Valider, pas échapper, à l'entrée. La validation d'entrée ne doit être que pour s'assurer que l'entrée a du sens, pas qu'elle soit "sûre". Il est impossible de savoir à ce stade s'il est sûr, car vous ne connaissez pas tous les endroits où il sera utilisé.
  • Supposons que toutes les données sont dangereuses. Ne faites jamais l'hypothèse que certaines données ont été échappées, ou n'incluent pas de balises ou de guillemets ou d'entités ou autre. Comprenez que les entrées dangereuses peuvent provenir de n'importe où: en-têtes HTTP, cookies, paramètres d'URL, données d'importation en masse, etc.
  • Échapper au point d'utilisation. Échapper les données pour le contexte dans lequel elles sont utilisées, quand elles sont utilisées. Vous ne voulez vous échapper qu'une seule fois pour améliorer les performances? Nommez la variable de destination selon l'endroit où elle peut être utilisée en toute sécurité: jsstringsafeEmail, htmlattrsafeColor, htmltextsafeFullName, etc.
77
bonsaiviking

Quels sont, selon vous, les concepts indispensables pour leur transmettre?

  • Différence entre réfléchi et stocké - je m'en fiche vraiment.
  • Couches de défense - Oui. De nombreux développeurs ne comprennent pas la "défense en profondeur". Supposons que toutes les autres mesures d'atténuation ont échoué et que votre code est la chose last qui se trouve entre l'attaquant et la ressource vulnérable. Que pouvez-vous faire pour atténuer l'attaque?
  • Codage sécurisé et contexte des paramètres de codage - absolument.
  • et surtout, l'impact potentiel des vulnérabilités. -- absolument

Quoi d'autre? La grande chose qui manque à votre liste est: il existe un grand nombre d'outils et de techniques qui peuvent tous être utilisés pour atténuer ces vulnérabilités potentielles; la défense en profondeur suggère que nous en utilisons autant que possible.

  • Soyez sécurisé par conception, sécurisé par défaut. Pensez aux vulnérabilités à toutes les étapes de la conception et de la mise en œuvre. Assurez-vous que vous choisissez out d'être en sécurité lorsque cela est nécessaire de ne pas choisir in lorsque cela est nécessaire.
  • Créez des modèles de menace officiels. Où les données hostiles peuvent-elles entrer dans un système et où peuvent-elles en sortir? Quels sous-systèmes se font mutuellement confiance et lesquels ne le font pas? Si vous ne savez pas où se trouvent les limites, il est difficile de les durcir contre les attaques.
  • Les cordes sont l'ennemi. Les données doivent circuler dans des objets intelligents pouvant être composés intelligemment, et non dans des chaînes pouvant être concaténées et divisées.
  • Si vous utilisez une langue dotée d'un système de types, saisissez si les données sont corrompues ou non dans le système de types. Faites en sorte que le compilateur vous dise que vous affectez des données contaminées dans un contexte qui attend des données non contaminées.
  • Si vous n'avez pas de compilateur pour trouver vos bogues, émulez un système de type dans votre discipline de nommage. Si une variable contient des données entachées, ayez "entachées" quelque part dans son nom. Si vous affectez une valeur corrompue à une variable qui n'a pas "corrompu" dans son nom, vous venez de détecter un problème au moment de la révision du code plutôt que lorsque l'attaquant réussit.
  • Utilisez des outils d'analyse statique conçus par des professionnels de la sécurité pour trouver ce genre de problèmes; faites très attention à la sortie, même les faux positifs. Un faux positif indique que le code ne peut pas être considéré comme correct par un analyseur; cela signifie qu'il ne peut pas non plus être considéré comme correct par un être humain. Corrigez le code afin que l'outil ne trouve plus le faux positif.
  • Testez tout comme un attaquant, pas un utilisateur. S'il y a du code qui nettoie l'entrée, chargez un membre de votre équipe de l'attaquer. Les bogues de désinfection sont une source courante de vulnérabilités difficiles à repérer.
  • Faites des tests pour les erreurs de configuration en production. Les vulnérabilités XSS peuvent être causées par la désactivation accidentelle d'une validation ou d'une désinfection à des fins de débogage ou de test et par l'oubli de la réactiver, en poussant la mauvaise configuration en production, etc.
  • Etc.
19
Eric Lippert

Vous avez couvert la plupart des bases. Pour approfondir un peu vos points (certains d'entre eux sembleront évidents pour la plupart des lecteurs ici, mais ne seront pas nécessairement évidents pour tous les développeurs):

  • XSS peut se produire via GET et POST.
  • XSS est également un problème dans les backends administratifs.
  • XSS basé sur DOM existe.
  • Les défenses du navigateur existent, mais ne doivent pas être utilisées. Il en va de même pour les WAF et les en-têtes de serveur.
  • L'encodage doit se produire lors de l'impression et non lors de la réception de données.
  • Le contexte est vraiment important. L'encodage HTML n'est pas suffisant dans certaines situations.
  • L'échappement/encodage JavaScript et CSS est difficile. L'utilisation d'une bibliothèque existante est recommandée.
  • Tous les paramètres doivent être codés. Ce n'est pas une bonne approche de coder uniquement les paramètres qui semblent dangereux.
  • Un filtrage d'entrée supplémentaire est fortement recommandé (par exemple, si vous avez besoin d'un entier, vérifiez qu'il s'agit bien d'un entier, idéalement localisé dans une classe Input), mais ne devrait jamais être la seule ligne de défense.

Mais le point le plus important à mon avis: le codage HTML devrait se produire par défaut, en utilisant un moteur de modèle qui code tous les paramètres par défaut.

Si l'encodage se produit partout, il est trop facile de l'oublier une seule fois. Il est bien sûr toujours important de prendre soin de toutes les situations où l'encodage HTML n'est pas suffisant, mais la plupart des vulnérabilités XSS seront évitées par l'encodage par défaut.

9
tim

Je pense que les deux leçons les plus importantes à enseigner sont les suivantes:

  1. Si vous générez du balisage ou toute autre représentation textuelle structurée (par exemple, JSON, SQL, chaînes de requête d'URL) de manière ad hoc en concaténant des chaînes ensemble, alors arrêtez ce que vous faites immédiatement , et trouver ou construire un centralisé et coffre-fort bibliothèque pour le balisage ou la génération DOM.
  2. Ne faites pas confiance aux stratégies de prévention XSS qui vous obligent à effectuer l’une des actions suivantes:
    • Devinez ce que l'attaquant tentera ou tentera de déjouer l'attaquant. En particulier, les filtres côté entrée ont traditionnellement été déjoués par les attaquants et doivent être considérés avec suspicion.
    • Identifiez, maintes et maintes fois dans différents contextes, quelles variables sont des entrées "non fiables" que vous devez ensuite traiter de manière exceptionnelle. (Au contraire, toutes les entrées doivent être non approuvées par défaut - vous devez désactiver la protection XSS, pas y adhérer.)

Sur mon premier point: presque tous les problèmes d'injection proviennent du travail au mauvais niveau d'abstraction : les programmeurs concaténent des chaînes dans des situations où ils devraient utiliser plus -des opérations de niveau qui s'éloignent de la façon correcte de faire les choses. Et cela signifie que:

  1. Les programmeurs finissent par s'attaquer encore et encore au même problème délicat (échappement correct des valeurs de chaîne dans le contexte dans lequel elles sont insérées). Même s'ils réussissaient à chaque fois (peu probable!), Les solutions ne seraient jamais réutilisées.
  2. Étant donné que la responsabilité d'échapper correctement les valeurs de chaîne est diffusée dans toute la base de code au lieu d'être concentrée en un seul endroit, l'audit du code pour la sécurité et la résolution des problèmes deviennent plus difficiles de quelques ordres de grandeur.

Sur le deuxième point: une bonne leçon sur les dangers de s'appuyer sur le filtrage côté entrée serait de parcourir les OWASP XSS Filter Evasion Cheat Sheet . Considérez cette page comme documentant une tentative échouée après l'autre et une autre pour résoudre XSS grâce au filtrage côté entrée, et l'habileté que les attaquants ont pu utiliser pour contourner ce problème.

Vous voyez également souvent de nombreux conseils qui parlent d'entrées "non fiables" et de la façon de les traiter, ce qui est semé d'embûches car:

  • Déterminer quelles entrées peuvent être fiables représente beaucoup de travail, en particulier lorsque vous devez le faire encore et encore;
  • Vous pourriez incorrectement juger quelles entrées sont fiables;
  • Les intrants auxquels on peut faire confiance aujourd'hui peuvent ne pas être fiables demain.

OWASP XSS Prevention Cheat Sheet est un autre document vraiment excellent qui suit mes deux points. Il explique comment en toute sécurité insérer des chaînes arbitraires dans du code HTML généré dynamiquement, Documents CSS et Javascript. Si vous résolvez ce problème en un seul endroit (soit dans une bibliothèque tierce, soit dans votre base de code) et appliquez cette solution de manière cohérente, vous réussirez très bien - vous aurez "coupé la jugulaire" des vulnérabilités XSS.

6
Luis Casillas

Vous avez déjà énuméré certains des concepts les plus importants - la seule chose que j'ajouterais est l'ubiquité et la facilité des tests pour les vulns XSS. XSS est souvent la première vulnérabilité qui est enseignée, et après l'injection SQL peut-être la plus connue. Il est également trivial de rechercher, et de nombreux scanners d'applications comme burp et w3af pourront détecter automatiquement XSS.

Comprendre cela est important, car il explique pourquoi xss existe toujours: à peu près tous les sites ont une sorte de protection xss en place, mais sont toujours vulnérables lorsqu'un testeur ou un scanner intelligent est en mesure de trouver une entrée utilisateur que le développeur a oubliée. Pour développer en toute sécurité un logiciel sans xss, les développeurs doivent être conscients que les attaquants utilisent des vecteurs étranges pour soumettre des charges utiles - par exemple En-têtes HTTP, menus déroulants, tout ce qui peut être modifié dans un proxy HTTP.

1
Buffalo5ix

Le point le plus important à faire valoir, à mon humble avis, est que vous devez savoir ce que contient une variable (ou un champ de base de données). Vous devez savoir s'il s'agit de texte (et de quel jeu de caractères/encodage, dans ce cas), ou HTML (ou un attribut HTML, qui est encore un autre type de données), ou SQL, etc.

Ensuite, vous devez vous appliquer aux conversions appropriées lorsque vous devez passer de l'un à l'autre.

Le gros problème est que dans de nombreux cas, la représentation d'un morceau de texte (probablement le type de données le plus courant que vous pouvez manipuler) est la même qu'il s'agisse de texte, HTML, SQL, etc. (le texte "abc" est le même comme HTML abc ou SQL 'abc') et pour cette raison, les gens ont tendance à concaténer des bits ensemble sans aucune conversion.

Mais cela se cassera dès que vous rencontrerez des personnages qui ont une signification particulière dans l'un des contextes. Cela entraîne non seulement des problèmes de sécurité (injections XSS et SQL), mais également des problèmes de formatage (nous avons tous vu des sites qui commencent à afficher des entités HTML telles que &lt; quand ils devraient afficher <), car les utilisateurs oublient la conversion ou le font plusieurs fois.

Il est assez rare que vous ayez réellement besoin d'autoriser la saisie de HTML réel. Dans la plupart des cas, vous voulez du texte. Gardez simplement le texte tel qu'il est, manipulez-le tel quel. Mais une fois que vous voulez l'afficher (sur une page HTML), convertissez-le en HTML (en utilisant standard et testé bibliothèques/frameworks, pas votre recherche et remplacement improvisés basés sur des expressions rationnelles).

De même, vous le convertissez lorsque vous souhaitez créer une requête SQL (à l'aide de requêtes paramétrées, de préférence). Mais vous le conservez toujours tel quel.

De nombreux frameworks ajouteront des couches d'abstraction qui "masqueront" tout cela si vous les utilisez réellement. Mais nous savons tous que même avec les meilleurs outils, vous vous retrouverez toujours avec quelqu'un qui essaiera de créer un peu de HTML lui-même, donc ils doivent savoir ce qui doit être fait s'ils le font.

Si vous voulez/devez manipuler du HTML réel, vous entrez une dimension complètement différente en termes de problèmes XSS. Notez bien que cela peut être couvert en une heure ...

1
jcaron

XSS est sérieux

Effectuez une démonstration de XSS pour montrer qu'il a un impact réel, au-delà de alert('xss').

XSS nous affecte

Fournissez des statistiques, par ex. 17 défauts XSS dans nos produits ont été identifiés lors de tests de pénétration au cours de l'année écoulée.

La solution s'échappe

Montrez-leur la différence entre le code qui ne s'échappe pas et qui est vulnérable et le code qui s'échappe. Réessayez la démonstration et voyez comment elle échoue.

Bonne pratique de codage

Montrez-leur de bonnes manières de s'évader avec les langages et frameworks utilisés dans votre entreprise. Idéalement, un moteur de modèle qui effectue un échappement automatique. Si vous avez un seul langage/cadre dans toute l'entreprise, c'est plus facile. Sinon, montrez un exemple et dites-leur de lire le cadre particulier qu'ils utilisent.

pièges courants

Contexte de la page. Même si vous disposez d'un moteur de modèle d'échappement, les données non fiables dans un <script> la balise peut provoquer XSS.

Quelles données ne sont pas fiables? Par exemple, si vous récupérez un flux RSS à partir d'un site externe, il s'agit toujours d'un risque XSS, même s'il ne s'agit pas d'une entrée directe de l'utilisateur.

DOM XSS - l'utilisation de JavaScript eval et document.write peut provoquer XSS.

Défense en profondeur

Le CSP est une excellente défense en profondeur, mais peut être difficile à mettre en œuvre.

Les options de cookies et la validation des demandes peuvent être facilement implémentées, mais ne sont que des défenses partielles.

Demandez de l'aide

Lorsque vous faites quelque chose de difficile - comme permettre aux utilisateurs d'utiliser des balises HTML limitées dans les commentaires - demandez de l'aide à un spécialiste de la sécurité.

0
paj28