web-dev-qa-db-fra.com

Une valeur Request.Form potentiellement dangereuse a été détectée par le client

Chaque fois qu'un utilisateur poste quelque chose contenant < ou > dans une page de mon application Web, cette exception est levée.

Je ne veux pas entrer dans la discussion sur l'intérêt de lancer une exception ou de planter une application Web entière parce que quelqu'un a saisi un caractère dans une zone de texte, mais je cherche un moyen élégant de gérer cela.

Piéger l'exception et montrer

Une erreur est survenue, veuillez recopier et ressaisir l'intégralité de votre formulaire, mais cette fois, veuillez ne pas utiliser <

ne me semble pas assez professionnel.

Désactiver la post-validation (validateRequest="false") évitera certainement cette erreur, mais la page restera vulnérable à un certain nombre d'attaques.

Idéalement: quand une publication contenant des caractères restreints au HTML apparaît, cette valeur publiée dans la collection de formulaires sera automatiquement encodée en HTML . Ainsi, la propriété .Text de ma zone de texte sera something & lt; html & gt;.

Est-il possible de le faire avec un gestionnaire?

1379
Radu094

Je pense que vous l'attaquez du mauvais angle en essayant de coder toutes les données postées.

Notez qu'un "<" peut également provenir d'autres sources extérieures, telles qu'un champ de base de données, une configuration, un fichier, un flux, etc. 

De plus, "<" n'est pas intrinsèquement dangereux. C'est seulement dangereux dans un contexte spécifique: lors de l'écriture de chaînes qui n'ont pas été encodées en sortie HTML (à cause de XSS).

Dans d'autres contextes, différentes sous-chaînes sont dangereuses. Par exemple, si vous écrivez une URL fournie par l'utilisateur dans un lien, la sous-chaîne "javascript:" peut être dangereuse. Le caractère guillemet simple, en revanche, est dangereux lors de l’interpolation de chaînes dans des requêtes SQL, mais il est parfaitement sûr qu’il s’agisse d’une partie d’un nom soumis à partir d’un formulaire ou lu à partir d’un champ de base de données.

La ligne du bas est la suivante: vous ne pouvez pas filtrer la saisie aléatoire pour les caractères dangereux, car tout caractère peut être dangereux dans les bonnes circonstances. Vous devriez encoder au moment où certains caractères spécifiques peuvent devenir dangereux car ils se croisent dans un sous-langage différent où ils ont une signification particulière. Lorsque vous écrivez une chaîne en HTML, vous devez coder des caractères ayant une signification spéciale en HTML, à l'aide de Server.HtmlEncode. Si vous transmettez une chaîne à une instruction SQL dynamique, vous devez coder différents caractères (ou mieux, laissez le cadre le faire pour vous en utilisant des instructions préparées ou similaires).

Lorsque vous êtes certain de coder HTML partout où vous passez des chaînes au format HTML, définissez validateRequest="false" dans la directive <%@ Page ... %> de votre/vos fichier (s) .aspx.

Dans .NET 4, vous devrez peut-être faire un peu plus. Parfois, il est également nécessaire d’ajouter <httpRuntime requestValidationMode="2.0" /> à web.config ( reference ).

1028
JacquesB

Il existe une solution différente à cette erreur si vous utilisez ASP.NET MVC:

Échantillon C #:

[HttpPost, ValidateInput(false)]
public ActionResult Edit(FormCollection collection)
{
    // ...
}

Exemple Visual Basic:

<AcceptVerbs(HttpVerbs.Post), ValidateInput(False)> _
Function Edit(ByVal collection As FormCollection) As ActionResult
    ...
End Function
482
Zack Peterson

Dans ASP.NET MVC (à partir de la version 3), vous pouvez ajouter l'attribut AllowHtml à une propriété de votre modèle.

Il permet à une demande d'inclure un balisage HTML lors de la liaison du modèle en ignorant la validation de la demande pour la propriété.

[AllowHtml]
public string Description { get; set; }
384
Anthony Johnston

Si vous êtes sur .NET 4.0, assurez-vous de l'ajouter dans votre fichier web.config à l'intérieur des balises <system.web>:

<httpRuntime requestValidationMode="2.0" />

Dans .NET 2.0, la validation des demandes s’appliquait uniquement aux demandes aspx. Dans .NET 4.0, cela a été étendu pour inclure all request. Vous pouvez revenir à only effectuer la validation XSS lors du traitement de .aspx en spécifiant:

requestValidationMode="2.0"

Vous pouvez désactiver la demande de validation entièrement en spécifiant:

validateRequest="false"
206
JordanC

Pour ASP.NET 4.0, vous pouvez autoriser le balisage en tant qu'entrée pour des pages spécifiques au lieu de l'intégralité du site en plaçant l'ensemble dans un élément <location>. Cela garantira la sécurité de toutes vos autres pages. Vous n'avez PAS besoin de mettre ValidateRequest="false" dans votre page .aspx.

<configuration>
...
  <location path="MyFolder/.aspx">
    <system.web>
      <pages validateRequest="false" />
      <httpRuntime requestValidationMode="2.0" />
    </system.web>
  </location>
...
</configuration>

Il est plus sûr de contrôler cela dans votre web.config, car vous pouvez voir au niveau du site quelles pages autorisent le balisage en entrée.

Vous devez toujours valider par programme les entrées sur les pages où la validation des demandes est désactivée.

108
Carter Medlin

Les réponses précédentes sont excellentes, mais personne n'a dit comment exclure un seul champ de la validation pour les injections HTML/JavaScript. Je ne connais pas les versions précédentes, mais dans MVC3 Beta, vous pouvez le faire:

[HttpPost, ValidateInput(true, Exclude = "YourFieldName")]
public virtual ActionResult Edit(int id, FormCollection collection)
{
    ...
}

Ceci valide encore tous les champs sauf celui exclu. La bonne chose à ce sujet est que vos attributs de validation valident toujours le champ, mais que vous n’obtenez pas les exceptions "Une valeur Request.Form potentiellement dangereuse a été détectée par le client".

J'ai utilisé cela pour valider une expression régulière. J'ai créé mon propre ValidationAttribute pour voir si l'expression régulière est valide ou non. Comme les expressions régulières peuvent contenir quelque chose qui ressemble à un script, j'ai appliqué le code ci-dessus - l'expression régulière est toujours vérifiée si elle est valide ou non, mais pas si elle contient des scripts ou du code HTML.

70
gligoran

Dans ASP.NET MVC, vous devez définir requestValidationMode = "2.0" et validateRequest = "false" dans web.config et appliquer un attribut ValidateInput à l'action de votre contrôleur:

<httpRuntime requestValidationMode="2.0"/>

<configuration>
    <system.web>
        <pages validateRequest="false" />
    </system.web>
</configuration>

et

[Post, ValidateInput(false)]
public ActionResult Edit(string message) {
    ...
}
48
ranthonissen

Vous pouvez HTML encoder contenu de la zone de texte, mais malheureusement cela n'arrêtera pas l'exception. D'après mon expérience, il n'y a pas de solution et vous devez désactiver la validation de page. En faisant cela, vous dites: "Je vais faire attention, je promets."

45
Pavel Chuchuva

Pour MVC, ignorez la validation d'entrée en ajoutant 

[ValidateInput (false)]

au-dessus de chaque action dans le contrôleur.

42
A.Dara

Vous pouvez attraper cette erreur dans Global.asax. Je veux toujours valider, mais montrer un message approprié. Sur le blog indiqué ci-dessous, un échantillon comme celui-ci était disponible. 

    void Application_Error(object sender, EventArgs e)
    {
        Exception ex = Server.GetLastError();

        if (ex is HttpRequestValidationException)
        {
            Response.Clear();
            Response.StatusCode = 200;
            Response.Write(@"[html]");
            Response.End();
        }
    }

Redirection vers une autre page semble également être une réponse raisonnable à l'exception.

http://www.romsteady.net/blog/2007/06/how-to-catch-httprequestvalidationexcep.html

41
BenMaddox

N'oubliez pas que certains contrôles .NET encoderont automatiquement le résultat au format HTML. Par exemple, définir la propriété .Text sur un contrôle TextBox l'encodera automatiquement. Cela signifie spécifiquement convertir < en &lt;, > en &gt; et & en &amp;. Alors méfiez-vous de le faire ...

myTextBox.Text = Server.HtmlEncode(myStringFromDatabase); // Pseudo code

Cependant, la propriété .Text pour HyperLink, Literal et Label ne codera pas le code HTML, donc encapsulez Server.HtmlEncode (); autour de tout ce qui est défini sur ces propriétés est indispensable si vous souhaitez empêcher la sortie de <script> window.location = "http://www.google.com"; </script> dans votre page, puis son exécution.

Faites quelques essais pour voir ce qui est encodé et ce qui ne l’est pas.

33
Dominic Pettifer

La réponse à cette question est simple:

var varname = Request.Unvalidated["parameter_name"];

Cela désactiverait la validation pour la demande particulière.

31
flakomalo

Dans le fichier web.config, insérez l'élément httpRuntime avec l'attribut requestValidationMode = "2.0" dans les balises. Ajoutez également l'attribut validateRequest = "false" dans l'élément pages.

Exemple:

<configuration>
  <system.web>
   <httpRuntime requestValidationMode="2.0" />
  </system.web>
  <pages validateRequest="false">
  </pages>
</configuration>
27
Mahdi jokar

Si vous ne souhaitez pas désactiver ValidateRequest, vous devez implémenter une fonction JavaScript afin d'éviter l'exception. Ce n'est pas la meilleure option, mais ça marche.

function AlphanumericValidation(evt)
{
    var charCode = (evt.charCode) ? evt.charCode : ((evt.keyCode) ? evt.keyCode :
        ((evt.which) ? evt.which : 0));

    // User type Enter key
    if (charCode == 13)
    {
        // Do something, set controls focus or do anything
        return false;
    }

    // User can not type non alphanumeric characters
    if ( (charCode <  48)                     ||
         (charCode > 122)                     ||
         ((charCode > 57) && (charCode < 65)) ||
         ((charCode > 90) && (charCode < 97))
       )
    {
        // Show a message or do something
        return false;
    }
}

Puis dans le code derrière, sur l'événement PageLoad, ajoutez l'attribut à votre contrôle avec le code suivant:

Me.TextBox1.Attributes.Add("OnKeyPress", "return AlphanumericValidation(event);")
23
YORENGOY

Il semble que personne n’a encore mentionné le point ci-dessous, mais cela résout le problème pour moi. Et avant que quiconque ne dise oui, c'est Visual Basic ... beurk.

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Example.aspx.vb" Inherits="Example.Example" **ValidateRequest="false"** %>

Je ne sais pas s'il y a des inconvénients, mais pour moi, cela a fonctionné à merveille.

20
Piercy

Une autre solution est:

protected void Application_Start()
{
    ...
    RequestValidator.Current = new MyRequestValidator();
}

public class MyRequestValidator: RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        bool result = base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);

        if (!result)
        {
            // Write your validation here
            if (requestValidationSource == RequestValidationSource.Form ||
                requestValidationSource == RequestValidationSource.QueryString)

                return true; // Suppress error message
        }
        return result;
    }
}
17
Sel

Si vous utilisez Framework 4.0, alors l'entrée dans le fichier web.config (<pages validateRequest = "false" />)

<configuration>
    <system.web>
        <pages validateRequest="false" />
    </system.web>
</configuration>

Si vous utilisez Framework 4.5, alors l'entrée dans le web.config (requestValidationMode = "2.0")

<system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" requestValidationMode="2.0"/>
</system.web>

Si vous voulez seulement une page alors, dans votre fichier aspx, vous devriez mettre la première ligne comme ceci:

<%@ Page EnableEventValidation="false" %>

si vous avez déjà quelque chose comme <% @ Page alors ajoutez simplement le reste => EnableEventValidation="false"%>

Je recommande de ne pas le faire.

14
Durgesh Pandey

Dans ASP.NET, vous pouvez capturer l'exception et y remédier, par exemple en affichant un message convivial ou en redirigeant vers une autre page ... Il est également possible que vous puissiez gérer la validation par vous-même ...

Afficher un message amical:

protected override void OnError(EventArgs e)
{
    base.OnError(e);
    var ex = Server.GetLastError().GetBaseException();
    if (ex is System.Web.HttpRequestValidationException)
    {
        Response.Clear();
        Response.Write("Invalid characters."); //  Response.Write(HttpUtility.HtmlEncode(ex.Message));
        Response.StatusCode = 200;
        Response.End();
    }
}
13
Jaider

Je suppose que vous pourriez le faire dans un module; mais cela laisse quelques questions ouvertes; Et si vous voulez sauvegarder les données dans une base de données? Du coup, parce que vous enregistrez des données codées dans la base de données, vous finissez par avoir confiance en ses données, ce qui est probablement une mauvaise idée. Idéalement, vous stockez des données brutes non codées dans la base de données et vous les encodez à chaque fois.

Désactiver la protection au niveau de chaque page puis encoder à chaque fois est une meilleure option.

Plutôt que d'utiliser Server.HtmlEncode, vous devriez vous intéresser à la bibliothèque plus récente, plus complète Anti-XSS de l'équipe Microsoft ACE.

12
blowdart

Les autres solutions ici sont Nice, mais il est un peu royal d’avoir à appliquer [AllowHtml] à chaque propriété Model, en particulier si vous avez plus de 100 modèles sur un site de taille décente.

Si, comme moi, vous souhaitez désactiver cette fonctionnalité (à mon humble avis plutôt inutile) hors du site, vous pouvez remplacer la méthode Execute () dans votre contrôleur de base (si vous ne possédez pas déjà de contrôleur de base, je vous suggère d'en créer un, ils peuvent le faire. très utile pour appliquer des fonctionnalités communes).

    protected override void Execute(RequestContext requestContext)
    {
        // Disable requestion validation (security) across the whole site
        ValidateRequest = false;
        base.Execute(requestContext);
    }

Assurez-vous simplement que vous codez en HTML tout ce qui est pompé dans les vues générées par l’entrée utilisateur (son comportement par défaut dans ASP.NET MVC 3 avec Razor de toute façon, donc à moins que pour une raison étrange vous utilisiez Html.Raw ne devrait pas nécessiter cette fonctionnalité.

10
magritte

Désactivez la validation de la page si vous avez réellement besoin des caractères spéciaux tels que, >, <, etc. Assurez-vous ensuite que, lorsque la saisie de l'utilisateur est affichée, les données sont codées en HTML. 

Il y a une faille de sécurité avec la validation de la page, elle peut donc être contournée. De plus, la validation de la page ne doit pas être invoquée uniquement.

Voir: http://web.archive.org/web/20080913071637/http://www.procheckup.com:80/PDFs/bypassing-dot-NET-ValidateRequest.pdf

9
woany

Cause

Par défaut, ASP.NET valide tous les contrôles d'entrée pour les contenus potentiellement dangereux pouvant entraîner/ la création de scripts intersite (XSS) et les injections SQL . Ainsi, il refuse un tel contenu en lançant l'exception ci-dessus. Par défaut, il est recommandé d'autoriser cette vérification à chaque publication.

Solution

Vous avez souvent besoin de soumettre du contenu HTML à votre page via des zones de texte riches ou des éditeurs de texte enrichi. Dans ce cas, vous pouvez éviter cette exception en définissant la balise ValidateRequest dans la directive @Page sur false.

<%@ Page Language="C#" AutoEventWireup="true" ValidateRequest = "false" %>

Cela désactivera la validation des demandes pour la page pour laquelle vous avez défini l'indicateur ValidateRequest sur false. Si vous souhaitez désactiver cela, vérifiez tout au long de votre application Web; vous devrez le définir sur false dans la section web.config <system.web>

<pages validateRequest ="false" />

Pour les frameworks .NET 4.0 ou supérieurs, vous devrez également ajouter la ligne suivante dans la section <system.web> pour que cela fonctionne.

<httpRuntime requestValidationMode = "2.0" />

C'est tout. J'espère que cela vous aidera à vous débarrasser de ce problème.

Référence par: Erreur ASP.Net: une valeur Request.Form potentiellement dangereuse a été détectée par le client

9
vakeel

J'ai trouvé une solution qui utilise JavaScript pour coder les données, qui sont décodées en .NET (et ne nécessitent pas jQuery).

  • Faites de la zone de texte un élément HTML (comme textarea) au lieu de ASP.
  • Ajouter un champ caché.
  • Ajoutez la fonction JavaScript suivante à votre en-tête.

    fonction boo () { targetText = document.getElementById ("HiddenField1"); sourceText = document.getElementById ("userbox"); targetText.value = escape (sourceText.innerText); }

Dans votre zone de texte, incluez un onchange qui appelle boo ():

<textarea id="userbox"  onchange="boo();"></textarea>

Enfin, dans .NET, utilisez

string val = Server.UrlDecode(HiddenField1.Value);

Je suis conscient que c'est un sens - si vous avez besoin d'un sens, vous devrez faire preuve de créativité, mais cela fournit une solution si vous ne pouvez pas éditer le fichier web.config.

Voici un exemple que je (MC9000) est venu avec et utiliser via jQuery:

$(document).ready(function () {

    $("#txtHTML").change(function () {
        var currentText = $("#txtHTML").text();
        currentText = escape(currentText); // Escapes the HTML including quotations, etc
        $("#hidHTML").val(currentText); // Set the hidden field
    });

    // Intercept the postback
    $("#btnMyPostbackButton").click(function () {
        $("#txtHTML").val(""); // Clear the textarea before POSTing
                               // If you don't clear it, it will give you
                               // the error due to the HTML in the textarea.
        return true; // Post back
    });


});

Et le balisage:

<asp:HiddenField ID="hidHTML" runat="server" />
<textarea id="txtHTML"></textarea>
<asp:Button ID="btnMyPostbackButton" runat="server" Text="Post Form" />

Cela fonctionne très bien. Si un pirate informatique tente de publier en contournant JavaScript, il verra simplement l'erreur. Vous pouvez également sauvegarder toutes ces données encodées dans une base de données, puis les décompresser (côté serveur), puis analyser et rechercher les attaques avant de les afficher ailleurs.

9
Jason Shuler

J'avais aussi cette erreur.

Dans mon cas, un utilisateur a entré un caractère accentué á dans un nom de rôle (concernant le fournisseur d'appartenance ASP.NET).

Je passe le nom du rôle à une méthode pour accorder aux utilisateurs ce rôle et la demande de publication $.ajax échouait lamentablement ...

J'ai fait ceci pour résoudre le problème:

Au lieu de

data: { roleName: '@Model.RoleName', users: users }

Faire ceci

data: { roleName: '@Html.Raw(@Model.RoleName)', users: users }

@Html.Raw a fait l'affaire.

Je recevais le nom du rôle en tant que valeur HTML roleName="Cadastro b&#225;s". Cette valeur avec l'entité HTML &#225; était bloquée par ASP.NET MVC. Maintenant, je reçois la valeur du paramètre roleName telle qu'elle devrait être: roleName="Cadastro Básico" et le moteur ASP.NET MVC ne bloquera plus la demande.

9
Leniel Maccaferri

Vous pouvez également utiliser la fonction escape (string) de JavaScript pour remplacer les caractères spéciaux. Ensuite, côté serveur, utilisez Server. URLDecode (string) pour le rétablir.

De cette façon, vous n'avez pas à désactiver la validation des entrées et il sera plus clair pour les autres programmeurs que la chaîne peut contenir du contenu HTML.

7
Trisped

J'ai utilisé JavaScript avant chaque publication pour rechercher les caractères que vous ne vouliez pas, tels que:

<asp:Button runat="server" ID="saveButton" Text="Save" CssClass="saveButton" OnClientClick="return checkFields()" />

function checkFields() {
    var tbs = new Array();
    tbs = document.getElementsByTagName("input");
    var isValid = true;
    for (i=0; i<tbs.length; i++) {
        if (tbs(i).type == 'text') {
            if (tbs(i).value.indexOf('<') != -1 || tbs(i).value.indexOf('>') != -1) {
                alert('<> symbols not allowed.');
                isValid = false;
            }
        }
    }
    return isValid;
}

Certes, ma page est principalement une saisie de données et très peu d’éléments font des publications, mais au moins leurs données sont conservées.

6
Ryan

Tant qu'il s'agit de uniquement "<" et ">" (et non de la citation double elle-même) et que vous les utilisez dans un contexte comme <input value = "this" /> , vous êtes en sécurité (alors que pour <textarea> celui-ci </ textarea>, vous seriez vulnérable bien sûr). Cela simplifiera peut-être votre situation, mais pour rien, utilisez une des solutions proposées.

4
Paweł Hajdan

Si vous souhaitez simplement dire à vos utilisateurs que <et> ne doivent pas être utilisés MAIS, vous ne voulez pas que le formulaire soit entièrement traité/renvoyé (et que vous perdiez toute la saisie) à l'avance, vous ne pourriez pas simplement mettre une un validateur autour du champ pour rechercher ces caractères (et peut-être d’autres potentiellement dangereux)?

4
Captain Toad

Vous pouvez utiliser quelque chose comme:

var nvc = Request.Unvalidated().Form;

Plus tard, nvc["yourKey"] devrait fonctionner.

4
Ady Levy

Aucune des suggestions n'a fonctionné pour moi. Je ne voulais de toute façon pas désactiver cette fonctionnalité pour l’ensemble du site Web, car 99% du temps, je ne veux pas que les utilisateurs placent du HTML sur des formulaires Web. Je viens de créer ma propre méthode de contournement puisque je suis le seul à utiliser cette application particulière. Je convertis l'entrée en HTML dans le code situé derrière et l'insère dans ma base de données.

4
Mike S.

Vous pouvez automatiquement coder le champ HTML dans le classeur de modèle personnalisé. Ma solution quelque peu différente, je mets une erreur dans ModelState et affiche un message d'erreur près du champ. Il est facile de modifier ce code pour encoder automatiquement 

 public class AppModelBinder : DefaultModelBinder
    {
        protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
        {
            try
            {
                return base.CreateModel(controllerContext, bindingContext, modelType);
            }
            catch (HttpRequestValidationException e)
            {
                HandleHttpRequestValidationException(bindingContext, e);
                return null; // Encode here
            }
        }
        protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext,
            PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
        {
            try
            {
                return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
            }
            catch (HttpRequestValidationException e)
            {
                HandleHttpRequestValidationException(bindingContext, e);
                return null; // Encode here
            }
        }

        protected void HandleHttpRequestValidationException(ModelBindingContext bindingContext, HttpRequestValidationException ex)
        {
            var valueProviderCollection = bindingContext.ValueProvider as ValueProviderCollection;
            if (valueProviderCollection != null)
            {
                ValueProviderResult valueProviderResult = valueProviderCollection.GetValue(bindingContext.ModelName, skipValidation: true);
                bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
            }

            string errorMessage = string.Format(CultureInfo.CurrentCulture, "{0} contains invalid symbols: <, &",
                     bindingContext.ModelMetadata.DisplayName);

            bindingContext.ModelState.AddModelError(bindingContext.ModelName, errorMessage);
        }
    }

Dans Application_Start:

ModelBinders.Binders.DefaultBinder = new AppModelBinder();

Notez que cela ne fonctionne que pour les champs de formulaire. Valeur dangereuse non transmise au modèle de contrôleur, mais stockée dans ModelState et pouvant être réaffichée sur le formulaire avec un message d'erreur. 

Les caractères dangereux dans l'URL peuvent être traités de la manière suivante:

private void Application_Error(object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    HttpContext httpContext = HttpContext.Current;

    HttpException httpException = exception as HttpException;
    if (httpException != null)
    {
        RouteData routeData = new RouteData();
        routeData.Values.Add("controller", "Error");
        var httpCode = httpException.GetHttpCode();
        switch (httpCode)
        {
            case (int)HttpStatusCode.BadRequest /* 400 */:
                if (httpException.Message.Contains("Request.Path"))
                {
                    httpContext.Response.Clear();
                    RequestContext requestContext = new RequestContext(new HttpContextWrapper(Context), routeData);
                    requestContext.RouteData.Values["action"] ="InvalidUrl";
                    requestContext.RouteData.Values["controller"] ="Error";
                    IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
                    IController controller = factory.CreateController(requestContext, "Error");
                    controller.Execute(requestContext);
                    httpContext.Server.ClearError();
                    Response.StatusCode = (int)HttpStatusCode.BadRequest /* 400 */;
                }
                break;
        }
    }
}

ErrorController: 

public class ErrorController : Controller
 {
   public ActionResult InvalidUrl()
   {
      return View();
   }
}   
3
Sel

Vous devez utiliser la méthode Server.HtmlEncode pour protéger votre site des entrées dangereuses.

Plus d'infos ici

3
bastos.sergio

Comme indiqué dans mon commentaire à la réponse de Sel , ceci est notre extension à un validateur de requête personnalisé.

public class SkippableRequestValidator : RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        if (collectionKey != null && collectionKey.EndsWith("_NoValidation"))
        {
            validationFailureIndex = 0;
            return true;
        }

        return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
    }
}
2
Walden Leverich

Pour ceux qui n'utilisent pas de liaison de modèle, qui extraient chaque paramètre du Request.Form, et qui sont certains que le texte saisi ne causera aucun dommage, il existe un autre moyen. Ce n'est pas une bonne solution, mais cela fera l'affaire. 

Du côté client, encodez-le comme uri puis envoyez-le.
par exemple: 

encodeURIComponent($("#MsgBody").val());  

Du côté du serveur, acceptez-le et décodez-le en tant que uri.
par exemple: 

string temp = !string.IsNullOrEmpty(HttpContext.Current.Request.Form["MsgBody"]) ?
System.Web.HttpUtility.UrlDecode(HttpContext.Current.Request.Form["MsgBody"]) : 
null;  

ou 

string temp = !string.IsNullOrEmpty(HttpContext.Current.Request.Form["MsgBody"]) ?
System.Uri.UnescapeDataString(HttpContext.Current.Request.Form["MsgBody"]) : 
null; 

veuillez rechercher les différences entre UrlDecode et UnescapeDataString

2
Wahid Masud

Enfin, notez les contrôles de liaison de données ASP.NET automatiquement encoder valeurs lors de la liaison de données. Cela modifie le comportement par défaut de tous les contrôles ASP.NET (TextBox, Label, etc.) contenus dans ItemTemplate. L'exemple suivant montre (ValidateRequest est défini sur false):

aspx

<%@ Page Language="C#" ValidateRequest="false" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication17._Default" %> <html> <body>
    <form runat="server">
        <asp:FormView ID="FormView1" runat="server" ItemType="WebApplication17.S" SelectMethod="FormView1_GetItem">
            <ItemTemplate>
                <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
                <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
                <asp:Label ID="Label1" runat="server" Text="<%#: Item.Text %>"></asp:Label>
                <asp:TextBox ID="TextBox2" runat="server" Text="<%#: Item.Text %>"></asp:TextBox>
            </ItemTemplate>
        </asp:FormView>
    </form> 

code derrière

public partial class _Default : Page
{
    S s = new S();

    protected void Button1_Click(object sender, EventArgs e)
    {
        s.Text = ((TextBox)FormView1.FindControl("TextBox1")).Text;
        FormView1.DataBind();
    }

    public S FormView1_GetItem(int? id)
    {
        return s;
    }
}

public class S
{
    public string Text { get; set; }
}
  1. Valeur de soumission du cas: &#39;

Label1.Text valeur: &#39;

TextBox2.Text valeur: &amp;#39;

  1. Valeur de soumission du cas: <script>alert('attack!');</script>

Label1.Text valeur: <script>alert('attack!');</script>

TextBox2.Text valeur: &lt;script&gt;alert(&#39;attack!&#39;);&lt;/script&gt;

1
dpant

Pour ceux qui sont encore bloqués sur les formulaires Web, j'ai trouvé la solution suivante qui vous permet de ne désactiver que la validation sur un champ! (Je ne voudrais pas le désactiver pour la page entière.)

VB.NET:

Public Class UnvalidatedTextBox
    Inherits TextBox
    Protected Overrides Function LoadPostData(postDataKey As String, postCollection As NameValueCollection) As Boolean
        Return MyBase.LoadPostData(postDataKey, System.Web.HttpContext.Current.Request.Unvalidated.Form)
    End Function
End Class

C #:

public class UnvalidatedTextBox : TextBox
{
    protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
    {
        return base.LoadPostData(postDataKey, System.Web.HttpContext.Current.Request.Unvalidated.Form);
    }
}

Maintenant, utilisez simplement <prefix:UnvalidatedTextBox id="test" runat="server" /> au lieu de <asp:TextBox, et il devrait autoriser tous les caractères (parfait pour les champs de mot de passe!)

1
Peter

Je sais que cette question concerne l'envoi de formulaires, mais j'aimerais ajouter quelques détails aux personnes qui ont reçu cette erreur dans d'autres circonstances. Cela pourrait également se produire sur un gestionnaire utilisé pour implémenter un service Web. 

Supposons que votre client Web envoie POST ou PUT des demandes à l'aide de ajax et envoie du texte json ou xml ou des données brutes (un contenu de fichier) à votre service Web. Étant donné que votre service Web n'a besoin d'obtenir aucune information d'un en-tête Content-Type, votre code JavaScript n'a pas défini cet en-tête pour votre demande ajax. Mais si vous ne définissez pas cet en-tête sur une requête ajax POST/PUT, Safari peut ajouter cet en-tête: "Type de contenu: application/x-www-form-urlencoded". J'ai observé cela sur Safari 6 sur iPhone, mais d'autres versions de Safari/OS ou de Chrome peuvent faire la même chose. Ainsi, lors de la réception de cet en-tête Content-Type, certaines parties de .NET Framework supposent que la structure de données du corps de la demande correspond à une publication de formulaire HTML, alors qu'elle ne le fait pas et génère une exception HttpRequestValidationException. La première chose à faire est évidemment de toujours définir l'en-tête Content-Type sur autre chose qu'un type MIME de formulaire sur une requête ajax POST/PUT, même si elle est inutile pour votre service Web.

J'ai aussi découvert ce détail:
Dans ces circonstances, l'exception HttpRequestValidationException est déclenchée lorsque votre code tente d'accéder à la collection HttpRequest.Params. Mais étonnamment, cette exception n’est pas levée lorsqu’il accède à la collection HttpRequest.ServerVariables. Cela montre que, bien que ces deux collections semblent presque identiques, l’une accède aux données de la demande par le biais de contrôles de sécurité et l’autre pas.

1
figolu

Dans .Net 4.0 et les versions ultérieures, ce qui est le cas habituel, définissez le paramètre suivant dans system.web

<system.web>
     <httpRuntime requestValidationMode="2.0" />
1
Kiran Chaudhari

dans mon cas, en utilisant asp: contrôle Textbox (Asp.net 4.5), au lieu de définir la page entière pour validateRequest="false" i utilisé 

<asp:TextBox runat="server" ID="mainTextBox"
            ValidateRequestMode="Disabled"
 ></asp:TextBox>

sur la zone de texte qui a provoqué l'exception.

0
maozx

Une solution

Je n'aime pas désactiver la post-validation (validateRequest = "false"). D'un autre côté, il est inacceptable que l'application se bloque simplement parce qu'un utilisateur innocent est en train de taper <x ou quelque chose du genre. 

J'ai donc écrit une fonction javascript côté client (xssCheckValidates) qui effectue une vérification préliminaire. Cette fonction est appelée lorsqu’on tente de publier les données de formulaire, comme ceci:

<form id="form1" runat="server" onsubmit="return xssCheckValidates();">

La fonction est assez simple et pourrait être améliorée, mais il fait son travail.

Veuillez noter que le but de ceci n'est pas de protéger le système contre le piratage, mais de protéger les utilisateurs d'une mauvaise expérience. La validation de la demande effectuée sur le serveur est toujours activée et fait partie de la protection du système (dans la mesure où il en est capable). 

La raison pour laquelle je dis "partie de" ici est parce que j'ai entendu dire que la validation de requête intégrée pourrait ne pas suffire, de sorte que d'autres moyens complémentaires pourraient être nécessaires pour bénéficier d'une protection complète. Mais, encore une fois, la fonction javascript que je présente ici a rien à voir avec la protection du système. C'est seulement _ conçu pour s'assurer que les utilisateurs n'auront pas une mauvaise expérience.

Vous pouvez l'essayer ici:

    function xssCheckValidates() {
      var valid = true;
      var inp = document.querySelectorAll(
          "input:not(:disabled):not([readonly]):not([type=hidden])" +
          ",textarea:not(:disabled):not([readonly])");
      for (var i = 0; i < inp.length; i++) {
        if (!inp[i].readOnly) {
          if (inp[i].value.indexOf('<') > -1) {
            valid = false;
            break;
          }
          if (inp[i].value.indexOf('&#') > -1) {
            valid = false;
            break;
          }
        }
      }
      if (valid) {
        return true;
      } else {
        alert('In one or more of the text fields, you have typed\r\nthe character "<" or the character sequence "&#".\r\n\r\nThis is unfortunately not allowed since\r\nit can be used in hacking attempts.\r\n\r\nPlease edit the field and try again.');
        return false;
      }
    }
<form onsubmit="return xssCheckValidates();" >
  Try to type < or &# <br/>
  <input type="text" /><br/>
  <textarea></textarea>
  <input type="submit" value="Send" />
</form>

0
Magnus

Utilisez le Server.HtmlEncode("yourtext");

0
Voigt

Je vois qu'il y a beaucoup d'écrits à ce sujet ... et je n'ai pas vu cela mentionné ... .. Ceci est disponible depuis .NET Framework 4.5

Le paramètre ValidateRequestMode pour un contrôle est une excellente option . Ainsi, les autres contrôles de la page sont toujours protégés. Aucune modification de web.config requise.

 protected void Page_Load(object sender, EventArgs e)
    {
             txtMachKey.ValidateRequestMode = ValidateRequestMode.Disabled;
    }
0
Chris Catignani