Question

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.

Interception de l'exception et affichage

  

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.

La désactivation de la post-validation (validateRequest="false") évitera définitivement cette erreur, mais laissera la page vulnérable à un certain nombre d'attaques.

Idéalement: lors d’une publication contenant des caractères restreints au HTML, cette valeur publiée dans la collection de formulaires sera automatiquement codée au format HTML. Donc, la .Text propriété de ma zone de texte sera something & lt; html & gt;

Y a-t-il un moyen de le faire avec un gestionnaire?

Était-ce utile?

La solution

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

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

En outre, " javascript: " 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 " validateRequest="false" " peut être dangereux. Le caractère entre guillemets, en revanche, est dangereux lors de l’interpolation de chaînes dans les requêtes SQL, mais il est parfaitement sûr qu’il s’agisse d’un nom de 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 une entrée 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 sûr de coder HTML partout où vous passez des chaînes au format HTML, définissez ensuite <%@ Page ... %> dans la directive .aspx de votre / vos fichier (s) .

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 ( référence ).

Autres conseils

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

Exemple 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

Dans ASP.NET MVC (à partir de la version 3), vous pouvez ajouter le AllowHtml attribut à une propriété sur 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; }

Si vous utilisez .NET 4.0, assurez-vous de l'ajouter dans votre fichier web.config dans les <system.web> tags:

.
<httpRuntime requestValidationMode="2.0" />

Dans .NET 2.0, la validation de requête s’appliquait uniquement aux aspx requêtes. Dans .NET 4.0, cela a été étendu pour inclure toutes les demandes. Vous pouvez rétablir uniquement l'exécution de la validation XSS lors du traitement .aspx en spécifiant:

requestValidationMode="2.0"

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

.
validateRequest="false"

Pour ASP.NET 4.0, vous pouvez autoriser le balisage en tant qu'entrée pour des pages spécifiques plutôt que pour l'ensemble du site en plaçant le tout dans un élément <location>. Cela garantira que toutes vos autres pages sont en sécurité. 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 préférable de contrôler cela dans votre Web.config, car vous pouvez voir au niveau du site quelles pages autorisent le balisage en tant qu'entrée.

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

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 toujours tous les champs sauf celui exclu. La bonne chose à ce propos est que vos attributs de validation continuent de valider le champ, mais que vous n’obtenez pas le & Quot; Une valeur Request.Form potentiellement dangereuse a été détectée par le client & Quot; exceptions.

Je l'ai utilisé 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, qu'elle soit valide ou non, mais pas si elle contient des scripts ou du code HTML.

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

<httpRuntime requestValidationMode="2.0"/>

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

et

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

Vous pouvez coder HTML . contenu de la boîte, mais malheureusement, cela n’empêchera pas l’exception de se produire. D'après mon expérience, il n'y a aucun moyen de contourner le problème et vous devez désactiver la validation de la page. En faisant cela, vous dites: & "Je ferai attention, je vous le promets. &";

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

  

[ValidateInput (false)]

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

Vous pouvez intercepter 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();
        }
    }

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

http://www.romsteady.net/ blog / 2007/06 / comment-attraper-httprequestvalidationexcep.html

La réponse à cette question est simple:

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

Ceci désactiverait la validation pour la requête particulière.

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 (); Pour éviter que <script> window.location = "http://www.google.com"; </script> soit affiché dans votre page et ensuite exécuté, tout ce qui est défini sur ces propriétés est indispensable.

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

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

Exemple:

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

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;
    }
}

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

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

Il semble que personne n'ait encore mentionné le texte 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.

Une autre solution consiste à:

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;
    }
}

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

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

Si vous utilisez Framework 4.5, l'entrée dans le fichier 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, 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.

Dans ASP.NET, vous pouvez capturer l'exception et faire quelque chose à son sujet, telle que l'affichage d'un message convivial ou la redirection vers une autre page ... Il est également possible que vous puissiez gérer la validation par vous-même ...

Afficher le message convivial:

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();
    }
}

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 l'encodage à chaque fois est une meilleure option.

Plutôt que d'utiliser Server.HtmlEncode, vous devriez vous intéresser au plus récent et plus complet Bibliothèque Anti-XSS de l'équipe Microsoft ACE.

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 d'un élément 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 aller-retour, vous devez faire preuve de créativité, mais cela fournit une solution si vous ne pouvez pas modifier 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) et analyser & Amp; vérifiez les attaques avant d’afficher ailleurs.

Cause

Par défaut, ASP.NET valide tous les contrôles d'entrée pour les contenus potentiellement non sécurisés pouvant conduire à la script intersite . (XSS) et 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 riche. 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" %>

Ceci 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 & # 8217; vous devrez le définir sur false dans votre Web.config < system.web > section

<pages validateRequest ="false" />

Pour les frameworks .NET 4.0 ou supérieurs, vous devrez également ajouter la ligne suivante dans le fichier < system.web > section pour faire le travail ci-dessus.

<httpRuntime requestValidationMode = "2.0" />

C'est & # 8217; 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

Les autres solutions ici sont bien, mais il est un peu pénible à l’arrière de devoir 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, inutile), 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 une, ils peuvent être très utiles 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é vers 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, sauf pour une raison étrange, vous utilisez Html.Raw. () vous ne devriez pas avoir besoin de cette fonctionnalité.

J'avais aussi cette erreur.

Dans mon cas, un utilisateur a saisi 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 attribuer ce rôle à des utilisateurs. La $.ajax demande de publication a échoué lamentablement ...

.

Je l'ai fait pour résoudre le problème:

Au lieu de

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

Faites ceci

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

@Html.Raw a fait le tour.

Je recevais le nom du rôle sous forme de valeur HTML roleName="Cadastro b&#225;s". Cette valeur avec l'entité HTML &#225; était bloquée par ASP.NET MVC. Maintenant, la valeur du paramètre roleName est la suivante: roleName="Cadastro Básico" et le moteur ASP.NET MVC ne bloque plus la demande.

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 existe une vulnérabilité de sécurité liée à la validation de la page. Elle peut donc être contournée. De plus, il ne faut pas compter uniquement sur la validation de page.

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

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

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

J'ai finalement 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 entrée de données. Très peu d'éléments font des publications, mais au moins leurs données sont conservées.

Tant qu'ils ne sont que & "; < &"; et " > " (et non la citation double elle-même) et vous les utilisez dans un contexte comme < valeur d'entrée = & "; this &"; / > ;, vous êtes en sécurité (alors que pour < textarea > celui-ci < / textarea > vous seriez vulnérable bien sûr). Cela peut simplifier la situation, mais pour n'importe quoi , utilisez davantage l’une des solutions proposées sur votre navigateur.

Si vous souhaitez simplement dire à vos utilisateurs que < et > ne doivent pas être utilisés MAIS, vous ne voulez pas que le formulaire entier soit traité / posté (et perdez toute entrée) avant de commencer, vous ne pourriez pas simplement mettre un validateur autour du champ pour filtrer ceux-ci (et peut-être d'autres potentiellement dangereux). ) caractères?

Aucune des suggestions n'a fonctionné pour moi. De toute façon, je ne voulais 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.

Vous pouvez utiliser quelque chose comme:

var nvc = Request.Unvalidated().Form;

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top