it-swarm-pt.tech

Um valor Request.Form potencialmente perigoso foi detectado no cliente

Toda vez que um usuário posta algo contendo < ou > em uma página em meu aplicativo da web, recebo essa exceção.

Não quero entrar na discussão sobre a inteligência de lançar uma exceção ou de bloquear um aplicativo da web inteiro porque alguém digitou um caractere em uma caixa de texto, mas estou procurando uma maneira elegante de lidar com isso.

Prendendo a exceção e mostrando

Ocorreu um erro, por favor, volte e digite novamente todo o seu formulário novamente, mas desta vez, por favor, não use <

não parece profissional o suficiente para mim.

Desabilitar a validação posterior (validateRequest="false") definitivamente evitará este erro, mas deixará a página vulnerável a vários ataques.

Idealmente: Quando um post back ocorre contendo caracteres HTML restritos, esse valor postado na coleção Form será automaticamente codificado em HTML. Assim, a propriedade .Text da minha caixa de texto será something & lt; html & gt;

Existe uma maneira de fazer isso de um manipulador?

1379
Radu094

Eu acho que você está atacando do ângulo errado, tentando codificar todos os dados postados.

Observe que um "<" também pode vir de outras fontes externas, como um campo de banco de dados, uma configuração, um arquivo, um feed e assim por diante. 

Além disso, "<" não é inerentemente perigoso. É perigoso apenas em um contexto específico: ao escrever strings que não foram codificadas para saída HTML (por causa do XSS).

Em outros contextos, diferentes subcordas são perigosas, por exemplo, se você gravar um URL fornecido pelo usuário em um link, a subcadeia "javascript:" poderá ser perigosa. O caractere de aspas simples, por outro lado, é perigoso ao interpolar strings em consultas SQL, mas é perfeitamente seguro se fizer parte de um nome enviado de um formulário ou lido em um campo de banco de dados.

A linha inferior é: você não pode filtrar a entrada aleatória para caracteres perigosos, porque qualquer personagem pode ser perigoso nas circunstâncias corretas. Você deve codificar no ponto em que alguns caracteres específicos podem se tornar perigosos porque eles se cruzam em um sub-idioma diferente, onde eles têm um significado especial. Quando você escreve uma string em HTML, você deve codificar caracteres que tenham um significado especial em HTML, usando Server.HtmlEncode. Se você passar uma string para uma instrução SQL dinâmica, deverá codificar caracteres diferentes (ou melhor, deixar a estrutura fazer isso por você usando instruções preparadas ou algo semelhante).

Quando tiver certeza de codificar em HTML em todos os lugares em que você passar strings para HTML, defina validateRequest="false" na diretiva <%@ Page ... %> em seu (s) arquivo (s) .aspx.

No .NET 4 você pode precisar fazer um pouco mais. Às vezes é necessário também adicionar <httpRuntime requestValidationMode="2.0" /> ao web.config ( reference ).

1028
JacquesB

Há uma solução diferente para esse erro se você estiver usando o ASP.NET MVC:

Amostra C #:

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

Exemplo do Visual Basic:

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

No ASP.NET MVC (iniciando na versão 3), você pode adicionar o atributo AllowHtml a uma propriedade em seu modelo.

Ele permite que uma solicitação inclua a marcação HTML durante a vinculação do modelo, ignorando a validação da solicitação para a propriedade.

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

Se você está no .NET 4.0, certifique-se de adicionar isto em seu arquivo web.config dentro das tags <system.web>:

<httpRuntime requestValidationMode="2.0" />

No .NET 2.0, a validação de solicitação é aplicada somente a solicitações aspx. No .NET 4.0, isso foi expandido para incluir all requests. Você pode reverter para only executando a validação de XSS ao processar .aspx especificando:

requestValidationMode="2.0"

Você pode desativar a solicitação validate entire, especificando:

validateRequest="false"
206
JordanC

Para o ASP.NET 4.0, você pode permitir a marcação como entrada para páginas específicas, em vez de todo o site, colocando tudo em um elemento <location>. Isso fará com que todas as outras páginas estejam seguras. Você NÃO precisa colocar ValidateRequest="false" na sua página .aspx.

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

É mais seguro controlar isso dentro de seu web.config, porque você pode ver em um nível de site quais páginas permitem marcação como entrada.

Você ainda precisa validar programaticamente a entrada nas páginas em que a validação da solicitação está desabilitada.

108
Carter Medlin

As respostas anteriores são ótimas, mas ninguém disse como excluir um único campo de ser validado para injeções de HTML/JavaScript. Eu não sei sobre versões anteriores, mas no MVC3 Beta você pode fazer isso:

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

Isso ainda valida todos os campos, exceto o excluído. O bom disso é que seus atributos de validação ainda validam o campo, mas você simplesmente não recebe as exceções "Um valor potencialmente perigoso de Request.Form foi detectado do cliente".

Eu usei isso para validar uma expressão regular. Eu fiz meu próprio ValidationAttribute para ver se a expressão regular é válida ou não. Como as expressões regulares podem conter algo parecido com um script, apliquei o código acima - a expressão regular ainda está sendo verificada se é válida ou não, mas não se contiver scripts ou HTML.

70
gligoran

No ASP.NET MVC, você precisa definir requestValidationMode = "2.0" e validateRequest = "false" no web.config e aplicar um atributo ValidateInput à sua ação do controlador:

<httpRuntime requestValidationMode="2.0"/>

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

e

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

Você pode HTML codificar conteúdo da caixa de texto, mas infelizmente isso não impedirá que a exceção aconteça. Na minha experiência, não há como fugir e você precisa desativar a validação da página. Ao fazer isso, você está dizendo: "Terei cuidado, prometo".

45
Pavel Chuchuva

Para MVC, ignore a validação de entrada adicionando 

[ValidateInput (false)]

acima de cada ação no controlador.

42
A.Dara

Você pode pegar esse erro no Global.asax. Eu ainda quero validar, mas mostro uma mensagem apropriada. No blog listado abaixo, uma amostra como essa estava disponível. 

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

Redirecionar para outra página também parece ser uma resposta razoável à exceção.

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

41
BenMaddox

Por favor, tenha em mente que alguns controles .NET automaticamente codificam a saída em HTML. Por exemplo, definir a propriedade .Text em um controle TextBox codificará automaticamente. Isso significa especificamente converter < em &lt;, > em &gt; e & em &amp;. Portanto, tenha cuidado ao fazer isso ...

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

No entanto, a propriedade .Text para HyperLink, Literal e Label não codificará as coisas em HTML, portanto, agrupando Server.HtmlEncode (); qualquer coisa que esteja sendo definida nessas propriedades é uma necessidade se você quiser impedir que <script> window.location = "http://www.google.com"; </script> seja enviado para a sua página e subsequentemente executado.

Faça um pouco de experimentação para ver o que é codificado e o que não é.

33
Dominic Pettifer

A resposta para essa pergunta é simples:

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

Isso desativaria a validação para a solicitação específica.

31
flakomalo

No arquivo web.config, dentro das tags, insira o elemento httpRuntime com o atributo requestValidationMode = "2.0". Adicione também o atributo validateRequest = "false" no elemento pages.

Exemplo:

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

Se você não quiser desabilitar o ValidateRequest, precisará implementar uma função JavaScript para evitar a exceção. Não é a melhor opção, mas funciona.

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

Em seguida, no code behind, no evento PageLoad, adicione o atributo ao seu controle com o próximo código:

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

Parece que ninguém mencionou o abaixo ainda, mas resolve o problema para mim. E antes que alguém diga sim é Visual Basic ... yuck.

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

Eu não sei se há alguma desvantagem, mas para mim isso funcionou incrível.

20
Piercy

Outra solução é:

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

Se você estiver usando o framework 4.0, então a entrada no web.config (<pages validateRequest = "false" />)

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

Se você estiver usando o framework 4.5 então a entrada no web.config (requestValidationMode = "2.0")

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

Se você quiser apenas uma página, então, em seu arquivo aspx você deve colocar a primeira linha como esta:

<%@ Page EnableEventValidation="false" %>

se você já tem algo como <% @ Página, basta adicionar o resto => EnableEventValidation="false"%>

Eu recomendo não fazer isso.

14
Durgesh Pandey

No ASP.NET, você pode capturar a exceção e fazer algo a respeito, como exibir uma mensagem amigável ou redirecionar para outra página ... Também há uma possibilidade de que você possa manipular a validação por si mesmo ...

Exibir mensagem amigável:

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

Eu acho que você poderia fazer isso em um módulo; mas isso deixa em aberto algumas questões; E se você quiser salvar a entrada em um banco de dados? De repente, porque você está salvando dados codificados no banco de dados, você acaba confiando na entrada, o que provavelmente é uma má ideia. Idealmente, você armazena dados não codificados brutos no banco de dados e codifica todas as vezes.

Desativar a proteção em um nível por página e, em seguida, codificar cada vez é uma opção melhor.

Em vez de usar Server.HtmlEncode, você deve examinar a biblioteca mais recente e mais completa de Anti-XSS da equipe do Microsoft ACE.

12
blowdart

As outras soluções aqui são agradáveis, no entanto, é um pouco real na parte traseira ter que aplicar [AllowHtml] a cada propriedade Model, especialmente se você tiver mais de 100 modelos em um site de tamanho decente.

Se como eu, você quer transformar este recurso (IMHO bastante sem sentido) fora do site você pode substituir o método Execute () em seu controlador de base (se você ainda não tem um controlador de base eu sugiro que você faça um, eles podem ser bastante útil para aplicar funcionalidade comum).

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

Apenas certifique-se de codificar em HTML tudo o que é bombeado para as visualizações que vieram da entrada do usuário (é um comportamento padrão no ASP.NET MVC 3 com o Razor, portanto, a menos que por alguma razão bizarra você esteja usando o Html.Raw () você não deve exigir esse recurso.

10
magritte

Desabilite a validação da página se você realmente precisar dos caracteres especiais como >, <, etc. Depois, certifique-se de que quando a entrada do usuário for exibida, os dados são codificados em HTML. 

Existe uma vulnerabilidade de segurança com a validação da página, portanto, ela pode ser ignorada. Além disso, a validação da página não deve ser confiada exclusivamente.

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

9
woany

Causa

Por padrão, o ASP.NET valida todos os controles de entrada para conteúdos potencialmente inseguros que podem levar a scripts entre sites (XSS) e injeções SQL . Assim, ele não permite tal conteúdo, lançando a exceção acima. Por padrão, é recomendável permitir que essa verificação aconteça em cada postback.

Solução

Em muitas ocasiões, você precisa enviar conteúdo HTML para sua página através de Rich TextBoxes ou Rich Text Editors. Nesse caso, você pode evitar essa exceção definindo a tag ValidateRequest na diretiva @Page como false.

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

Isso desativará a validação de solicitações para a página em que você definiu o sinalizador ValidateRequest como falso. Se você quiser desabilitar isso, verifique toda a sua aplicação web; você precisará configurá-lo para false em sua seção web.config <system.web>

<pages validateRequest ="false" />

Para estruturas .NET 4.0 ou superiores, você precisará incluir também a seguinte linha na seção <system.web> para fazer o trabalho acima.

<httpRuntime requestValidationMode = "2.0" />

É isso aí. Espero que isso ajude você a se livrar da questão acima.

Referência por: ASP.Net Error: Um valor Request.Form potencialmente perigoso foi detectado a partir do cliente

9
vakeel

Eu encontrei uma solução que usa JavaScript para codificar os dados, que é decodificado no .NET (e não requer jQuery).

  • Torne a caixa de texto um elemento HTML (como textarea) em vez de um elemento ASP.
  • Adicione um campo oculto.
  • Adicione a seguinte função JavaScript ao seu cabeçalho.

    função boo () { targetText = document.getElementById ("HiddenField1"); sourceText = document.getElementById ("userbox" ); targetText.value = escape (sourceText.innerText); }

Em sua textarea, inclua um onchange que chama boo ():

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

Finalmente, no .NET, use

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

Estou ciente de que isso é unidirecional - se você precisar de duas vias, terá que ser criativo, mas isso fornece uma solução se você não puder editar o arquivo web.config

Aqui está um exemplo que eu (MC9000) surgiu e uso 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
    });


});

E a marcação:

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

Isso funciona muito bem. Se um hacker tentar postar por meio do JavaScript, ele só verá o erro. Você também pode salvar todos esses dados codificados em um banco de dados, depois desencaixá-los (no lado do servidor) e analisar e verificar se há ataques antes de exibir em outro lugar.

9
Jason Shuler

Eu estava recebendo esse erro também.

No meu caso, um usuário digitou um caractere acentuado á em um Nome de Função (referente ao provedor de associação do ASP.NET).

Eu passei o nome da função para um método para conceder Usuários a essa função e a solicitação de postagem $.ajax estava falhando miseravelmente ...

Eu fiz isso para resolver o problema:

Ao invés de

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

Faça isso

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

@Html.Raw fez o truque.

Eu estava recebendo o nome da função como o valor HTML roleName="Cadastro b&#225;s". Este valor com a entidade HTML &#225; estava sendo bloqueado pelo ASP.NET MVC. Agora obtenho o valor do parâmetro roleName da maneira que deveria ser: roleName="Cadastro Básico" e o mecanismo ASP.NET MVC não bloquearão mais a solicitação.

9
Leniel Maccaferri

Você também pode usar a função escape (string) do JavaScript para substituir os caracteres especiais. Então, no lado do servidor, use Server. URLDecode (string) para alternar de volta.

Dessa forma, você não precisa desativar a validação de entrada e será mais claro para outros programadores que a sequência pode ter conteúdo HTML.

7
Trisped

Acabei usando JavaScript antes de cada postback para verificar os caracteres que você não queria, como:

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

Concedido a minha página é principalmente a entrada de dados, e há muito poucos elementos que fazem postbacks, mas pelo menos seus dados são mantidos.

6
Ryan

Contanto que estes sejam caracteres only "<" e ">" (e não as aspas duplas em si) e você os esteja usando no contexto como <input value = "this" />, é seguro (enquanto para <textarea> this one </ textarea> você seria vulnerável, é claro). Isso pode simplificar sua situação, mas para qualquer coisa mais, use uma das outras soluções postadas.

4
Paweł Hajdan

Se você está apenas querendo dizer aos seus usuários que <e> não devem ser usados ​​MAS, você não quer que o formulário inteiro seja processado/postado de volta (e perde toda a entrada) antes da mão não poderia simplesmente colocar em um validador em todo o campo para a tela para aqueles (e talvez outros potencialmente perigosos) caracteres?

4
Captain Toad

Você pode usar algo como:

var nvc = Request.Unvalidated().Form;

Mais tarde, nvc["yourKey"] deve funcionar.

4
Ady Levy

Nenhuma das sugestões funcionou para mim. Eu não queria desativar esse recurso para todo o site porque 99% do tempo eu não quero que meus usuários coloquem HTML em formulários da web. Acabei de criar meu próprio método de trabalho, já que sou o único que usa esse aplicativo em particular. Eu converto a entrada para HTML no código por trás e a insiro no meu banco de dados.

4
Mike S.

Você pode codificar automaticamente o campo de código HTML no Binder de Modelo personalizado. Minha solução é diferente, eu coloquei erro no ModelState e exibi mensagem de erro perto do campo. É fácil modificar este código para codificar automaticamente 

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

Em Application_Start:

ModelBinders.Binders.DefaultBinder = new AppModelBinder();

Observe que isso funciona apenas para campos de formulário. Valor perigoso não passado ao modelo do controlador, mas armazenado no ModelState e pode ser exibido novamente no formulário com a mensagem de erro. 

Chars perigosos em URL podem ser manipulados desta maneira:

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

Você deve usar o método Server.HtmlEncode para proteger seu site contra entradas perigosas.

Mais informações aqui

3
bastos.sergio

Como indicado no meu comentário para resposta de Sel , esta é a nossa extensão para um validador de solicitação personalizada.

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

Para aqueles que não estão usando a vinculação de modelo, que estão extraindo cada parâmetro do Request.Form, que tem certeza de que o texto de entrada não causará danos, existe outra maneira. Não é uma ótima solução, mas fará o trabalho. 

Do lado do cliente, codifique-o como uri e envie-o.
por exemplo: 

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

Do lado do servidor, aceite-o e decodifique-o como uri.
por exemplo: 

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; 

por favor, procure as diferenças entre UrlDecode e UnescapeDataString

2
Wahid Masud

Por último, mas não menos importante, por favor, note que o ASP.NET Data Binding controla automaticamente encode values ​​durante a vinculação de dados. Isso altera o comportamento padrão de todos os controles do ASP.NET (TextBox, Label etc) contidos no ItemTemplate. O exemplo a seguir demonstra (ValidateRequest está definido como 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> 

Código por trás

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. Valor de envio do caso: &#39;

Label1.Text value: &#39;

TextBox2.Text value: &amp;#39;

  1. Valor de envio do caso: <script>alert('attack!');</script>

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

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

1
dpant

Para aqueles de nós ainda presos em webforms, encontrei a seguinte solução que permite desativar somente a validação em um campo! (Eu odiaria desativá-lo para a página inteira.)

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

Agora é só usar <prefix:UnvalidatedTextBox id="test" runat="server" /> em vez de <asp:TextBox, e deve permitir todos os caracteres (isto é perfeito para campos de senha!)

1
Peter

Eu sei que essa pergunta é sobre postagem de formulários, mas gostaria de adicionar alguns detalhes para pessoas que receberam esse erro em outras circunstâncias. Também pode ocorrer em um manipulador usado para implementar um serviço da web. 

Suponha que seu cliente da Web envie solicitações POST ou PUT usando ajax e envie texto json ou xml ou dados brutos (um conteúdo de arquivo) para seu serviço da web. Como seu serviço da web não precisa obter nenhuma informação de um cabeçalho Content-Type, seu código JavaScript não configurou esse cabeçalho para sua solicitação ajax. Mas se você não definir este cabeçalho em um pedido ajax POST/PUT, o Safari poderá adicionar este cabeçalho: "Tipo de Conteúdo: application/x-www-form-urlencoded". Eu observei isso no Safari 6 no iPhone, mas outras versões Safari/OS ou Chrome podem fazer o mesmo. Portanto, ao receber esse cabeçalho Content-Type, parte do .NET Framework supõe que a estrutura de dados do corpo da solicitação corresponde a uma postagem de formulário html enquanto ela não existe e gerou uma exceção HttpRequestValidationException. A primeira coisa a fazer é, obviamente, sempre definir cabeçalho Content-Type para qualquer coisa, mas um tipo de formulário MIME em um pedido de POST/PUT ajax, mesmo que seja inútil para o seu serviço da web.

Eu também descobri esse detalhe:
Nessas circunstâncias, a exceção HttpRequestValidationException é aumentada quando seu código tenta acessar a coleção HttpRequest.Params. Mas, surpreendentemente, essa exceção não aumenta quando acessa a coleção HttpRequest.ServerVariables. Isso mostra que, embora essas duas coleções pareçam quase idênticas, uma acessa os dados da solicitação por meio de verificações de segurança e a outra não.

1
figolu

No .net 4.0 e em diante, que é o caso usual, coloque a seguinte configuração no system.web

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

no meu caso, usando asp: controle de caixa de texto (Asp.net 4.5), em vez de definir a página de todos para validateRequest="false" eu usei 

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

na caixa de texto que causou a exceção.

0
maozx

Uma solução

Eu não gosto de desativar a validação post (validateRequest = "false"). Por outro lado, não é aceitável que o aplicativo trave apenas porque um usuário inocente digita <x ou algo assim. 

Por isso, escrevi uma função javascript do lado do cliente (xssCheckValidates) que faz uma verificação preliminar. Essa função é chamada quando há uma tentativa de postar os dados do formulário, assim:

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

A função é bastante simples e pode ser melhorada, mas está fazendo o seu trabalho.

Por favor, observe que o propósito disso não é proteger o sistema contra hackers, mas sim proteger os usuários de uma experiência ruim. A validação da solicitação feita no servidor ainda está ativada e isso é (parte da) proteção do sistema (na medida em que é capaz de fazer isso). 

A razão pela qual eu digo "parte de" aqui é porque ouvi dizer que a validação da solicitação pode não ser suficiente, portanto, outros meios complementares podem ser necessários para ter proteção total. Mas, novamente, a função javascript que eu apresento aqui tem nothing a ver com proteger o sistema. É only significa que os usuários não terão uma experiência ruim.

Você pode experimentar aqui:

    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

Use o Server.HtmlEncode("yourtext");

0
Voigt

Eu vejo que há muito escrito sobre isso ... e eu não vi isso mencionado. Isso está disponível desde o .NET Framework 4.5

A configuração ValidateRequestMode para um controle é uma ótima opção. Dessa forma, os outros controles da página ainda estão protegidos. Nenhuma mudança no web.config é necessária.

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