Lors de la création d’un formulaire, la sécurisation de celui-ci est bien souvent mise de côté. Si le formulaire n’est pas assez sécurisé alors l’attaquant pourra obtenir diverses informations sur notre site (mot de passe, schéma de base de données, etc. ). Cela peux donc engendrer des conséquences désastreuses et porter atteinte à l’image du site. Dans cet article nous allons voir les différents types d’attaques et les moyens mis à notre disposition pour les éviter.

Voici la liste des différents types d’attaques auxquels nous pouvons être confronté si on ne protège pas nos formulaires :

  • XSS (Cross Site Scripting) : Injection de code indésirable dans des paramètres d’une URL ou dans un champ d’un formulaire.
  • CSRF (Cross Site Request Forgery) : Elle consiste à effectuer des opérations sur un site sans le consentement d’un utilisateur. (Pour de plus amples informations je vous invite à regarder ce lien http :/www. cert. ssi. gouv. fr/site/CERTA-2008-INF-003/)
  • Injection SQL : Modification d’une requête SQL existante grâce à un champ mal filtré. Ce type d’attaque permet de récupérer des informations sur la base de données, ‘bypasser’ l’authentification etc. L’attaquant se sert soit de l’url ou bien d’un formulaire.
  • Parameter Tampering : Attaque basée sur un formulaire en passant certains paramètres dans l’URL ou changement d’un champ d’un formulaire sans l’autorisation de l’utilisateur.
  • OverPosting : Poster des propriétés qui n’apparaissent pas dans le formulaire mais qui sont contenues dans le modèle du formulaire.

Il existe quelques techniques qui permettent d’éviter ou minimiser l’impact d’attaques :

  • La méthode du formulaire
  • ValidateAntiForgery
  • Clics multiples
  • Le contrôle des données
  • La spécialisation un modèle de classe pour chaque vue.
  • Captcha

La méthode du formulaire

Lors de la création d’un formulaire, on a le choix de faire transiter l’information par méthode GET ou POST.

La méthode GET, privilégiée surtout pour la recherche, transmet les informations dans l’url, cependant la taille est généralement limitée à 260 caractères. On peut modifier cette limite dans le web. config en utilisant 2 attributs de l’élément HttpRuntime.

<httpRuntime maxRequestPathLength="260" maxQueryStringLength="2048" />

La méthode POST, privilégiée pour l’ajout, la modification et le formulaire de connexion, n’a pas de limite de caractères dans l’url car l’information se situe dans le corps du message.

Note : si on écrit le code ci-dessous, la méthode par défaut sera le GET, penser à mettre [HttpGet] ou à retirer le [HttpPost] sur l’action du contrôleur qui reçoit le submit.

<form action="/home/create"> ... </form>

Par contre si on met le code ci-dessous, la méthode par défaut sera le POST

@using(Html.BeginForm("Create","Home")){ ... }

ValidateAntiForgery

Pour se protéger d’attaques du type CSRF, le Framework MVC met à notre disposition l’attribut ValidateAntiForgeryToken.

Il suffit d’ajouter cet attribut dans la méthode d’action de notre contrôleur qui va recevoir le formulaire. Ensuite au niveau html dans notre formulaire, il suffit d’ajouter @Html. AntiForgeryToken () Au niveau du rendu de la page, cela va générer un token dans un champ caché qui sera récupéré lors de l’appel de notre action POST du formulaire.

<input name="__RequestVerificationToken" type="hidden" value="hHPytP5nO6LULDPfHtD0-yrTiAxJrtGV29_O7Figu__gIR98E3t0aNYzSiWNGiO9YYESMQVXAduanp6QmMgAV7NuRrwVSCjV2dJyOmogJhY1">

Si le token est non présent lors de la création du formulaire et qu’il est mis sur l’action du contrôle alors par défaut il aura la page d’erreur ci-dessous :

Clics multiples

Quand le formulaire met trop de temps à s’exécuter, les utilisateurs ont tendance à cliquer une nouvelle fois sur le bouton “Envoyer”. Cela a pour conséquence d’envoyer plusieurs fois la demande à notre méthode qui reçoit le POST et de potentiellement créer autant d’enregistrements. Pour corriger cela, il suffit d’ajouter un code JavaScript permettant sa désactivation lors du 1er clic :

<form action="/Home/Contact" id="idForm" method="post>
    Nom : <input type="text" name="nom" />
    Prenom : <input type="text" name="prenom" />
    <input type="submit" id="btnSubmit" value="Envoyer" />
</form>
<script>
        $("#idForm").submit(function()
        {
            if ($('#idForm').valid()) {
                $("#btnSubmit").attr("disabled", "disabled");
                return true;
            }       
        });
    </script>

Le contrôle des données

1) Contrôle des champs visibles

Lors de l’envoi des informations d’un formulaire, l’attaquant va tenter d’ajouter un code dans un champ du formulaire pour ensuite récupérer des informations ou bien réussir à se connecter. Pour cela il faut faire des vérifications avant d’enregistrer les données en base. Et de même pour l’affichage.

Le traitement des entrées

Par défaut ASP.NET protège ce type d’attaque et envoie la page d’erreur ci-dessous.  Pour certains besoins, on est obligé de retirer cette vérification, cela ce fait par le biais de l’attribut [ValidateInput (false)] que l’on ajoute sur l’action de notre contrôleur.

Une fois cet attribut mis, il faut ajouter notre propre validation en utilisant la bibliothèque Sanitizer qui contient les méthodes GetSafeHtml ou GetSafeHtmlFragment. Ces méthodes permettent de nettoyer le html pour pouvoir l’enregistrer en base de données.

Exemple :

string chaine1 = "<script>alert('test');</script>";
string chaine2 = "<h1>titre</h1>";
string safeHtmlFragment = Sanitizer.GetSafeHtmlFragment(chaine1);
// résultat : chaine vide
string safeHtmlFragment2 = Sanitizer.GetSafeHtmlFragment(chaine2);
// résultat : titre
string safeHtml = Sanitizer.GetSafeHtml(chaine1);
// résult : <html>\r\n<head>\r\n</head>\r\n</html>\r\n
string safeHtml2 = Sanitizer.GetSafeHtml(chaine2);
// résultat : <html>\r\n<body>\r\ntitre\r\n</body>\r\n</html>\r\n

Traitement en sortie

Pour le moteur de vue Razor, toutes les sorties qui font appel à un HtmlHelper sont encodées, on peut aussi utiliser Html. Encode. Pour certains cas dans lesquels on a besoin d’interpréter la sortie sans l’encodée, on utilisera @Html. Raw ().

Exemple :

@{

string message = "<script>alert('Cross Site Scripting Attack!');</script>";
}
@Html.Raw(message); // Affiche la message box
mon message : @(message) //<script>alert('Cross site scripting attack!');</script>
mon message : @Html.Encode(message) //&lt;script&gt;alert(&#39;Cross site scripting attack!&#39;);&lt;/script&gt;

2) Contrôle d’un champ caché

Pour les formulaires d’édition, on a l’habitude de mettre en champ caché l’Id de l’objet mais sans le protéger. Voici le résultat dans l’exemple suivant et les dégâts que cela peut occasionner.

J’utilise Web Developper Tool dans FireFox pour afficher tous les champs de mon formulaire.

Je modifie directement le champ Id en ajoutant la valeur 34 (Capture ci-dessous)

Une fois mon formulaire validé, les informations contenues dans l’objet avec l’id 23 se retrouvent dans l’objet avec l’id 34.

Pour résoudre ce problème, il existe une solution qui consiste à ajouter notre champ caché Id et un champ caché contenant notre Id crypté. Lors du Post, on crée un ActionFilter qui va comparer l’id avec notre champ caché décrypté.

La démarche

J’utilise la Dll “Secure_Coding. MvcSecurityExtensions” qui se trouve a cette adresse : http ://mvcsecurity. codeplex. com/

Dans mon formulaire en édition, on ajoute :

@Html. HiddenFor (model => model. Id)

@Html. AntiModelInjectionFor (model => model. Id)

Ensuite dans mon action de mon contrôleur qui reçoit le formulaire en édition :

[ValidateAntiModelInjectionAttribute (”Id&rdquo ;)]

Vérification en images

Mon formulaire contient un champ caché nommé “_IdToken” et un champ caché “Id”

Si je modifie le champ caché “Id”, j’ai un message d’erreur. (Capture ci-dessous)

Le captcha

Le Captcha est une mesure de sécurité qui fait que la réponse ne peut pas être générée par un ordinateur mais par l’utilisateur. Cependant le Captcha n’est pas fiable à 100% car des personnes mal intentionnées peuvent utiliser des algorithmes de reconnaissance de caractère (OCR) pour obtenir le code. Il existe différentes manières de contourner un Captcha. Mais sa mise en place permet tout de même de se protéger du SPAM.

En ASP.NET MVC, il existe reCaptcha ou encore CaptchaMvc.

 

Dans ce 1er article, nous avons vu différentes techniques permettant d’augmenter la sécurité des formulaires. Dans la partie 2, nous allons créer un Captcha en ASP.NET MVC.

Ne ratez plus aucune actualité avec la newsletter mensuelle de SoftFluent

Newsletter SoftFluent