Pergunta

Cada vez que um usuário posta algo contendo < ou > em uma página do 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 travar um aplicativo Web inteiro porque alguém inseriu um caractere em uma caixa de texto, mas estou procurando uma maneira elegante de lidar com isso.

Capturando a exceção e mostrando

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

não parece profissional o suficiente para mim.

Desativando pós-validação (validateRequest="false") definitivamente evitará esse erro, mas deixará a página vulnerável a vários ataques.

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

Existe uma maneira de fazer isso com um manipulador?

Foi útil?

Solução

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

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

Além disso, "<" não é inerentemente perigoso. É apenas perigoso num contexto específico:. Ao escrever cordas que não foram codificados para a saída HTML (por causa de XSS)

Em outros contextos diferentes sub-cordas são perigosos, por exemplo, se você escrever um URL fornecido pelo usuário em um link, o sub-string "javascript:" pode ser perigoso. O caractere de aspas simples, por outro lado é perigoso quando interpolação cordas em consultas SQL, mas perfeitamente seguro se é uma parte de um nome apresentado de uma forma ou ler a partir de um campo de banco de dados.

A linha inferior é: você não pode filtrar a entrada aleatória para caracteres perigosos, pois qualquer personagem pode ser perigoso sob as circunstâncias corretas. Você deve codificar no ponto onde alguns personagens específicos pode tornar-se perigoso, porque eles cruzam em uma sub-idioma diferente, onde eles tem um significado especial. Quando você escreve uma string para HTML, você deve codificar caracteres que têm significado especial em HTML, usando Server.HtmlEncode. Se você passar uma string para uma instrução SQL dinâmica, você deve codificar caracteres diferentes (ou melhor, deixe o quadro fazê-lo para você, usando instruções preparadas ou similares) ..

Quando você tem certeza que HTML-codificar em todos os lugares que você passar cadeias para HTML, então o conjunto de validateRequest="false" na directiva <%@ Page ... %> em seu arquivo .aspx (s).

Em .NET 4 pode ser necessário fazer um pouco mais. Às vezes é necessário acrescentar também <httpRuntime requestValidationMode="2.0" /> para web.config ( referência ).

Outras dicas

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

C # exemplo:

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

Exemplo de Visual Basic:

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

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

Ele permite que um pedido para incluir HTML marcação durante a ligação saltando validação de solicitação para a propriedade modelo.

[AllowHtml]
public string Description { get; set; }

Se você estiver em .NET 4.0 Certifique-se de adicionar este em sua web.config arquivo dentro das tags <system.web>:

<httpRuntime requestValidationMode="2.0" />

Em .NET 2.0, validação de solicitação aplicada somente aos pedidos aspx. Em .NET 4.0 isso foi expandido para incluir todas solicitações. Você pode reverter para única de uma validação XSS ao processar .aspx especificando:

requestValidationMode="2.0"

Você pode desativar pedido validar inteiramente , especificando:

validateRequest="false"

Para ASP.NET 4.0, você pode permitir marcação como entrada para páginas específicas em vez de todo o site, colocando tudo isso em um elemento <location>. Isso irá garantir que todos os seus outros páginas são seguros. 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 para controlar esta dentro do seu web.config, porque você pode ver em um nível local, que páginas permitem marcação como entrada.

Você ainda precisará de entrada programaticamente validar nas páginas em que a validação de solicitação está desativado.

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

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

Este ainda valida todos os campos exceto o excluído. A coisa agradável sobre isso é que a sua validação ainda atributos validar o campo, mas você simplesmente não obter o "Um valor Request.Form potencialmente perigoso foi detectado do cliente" exceções.

Eu usei isso para validar uma expressão regular. Eu fiz a minha própria ValidationAttribute para ver se a expressão regular é válido ou não. Como expressões regulares podem conter algo que se parece com um roteiro que eu aplicado o código acima -. A expressão regular ainda está sendo verificado se ele é válido ou não, mas não se contém scripts ou HTML

Em 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) {
    ...
}

Você pode HTML codificar texto conteúdo da caixa, mas infelizmente isso não vai parar a exceção de acontecer. Na minha experiência, não há nenhuma maneira em torno, e você tem que validação página desativar. Ao fazer isso você está dizendo: "Serei cuidadoso, prometo"

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

[ValidateInput (false)]

acima de cada ação no controller.

Você pode pegar esse erro no Global.asax. Eu ainda quero validar, mas mostrar uma mensagem apropriada. No blog listado abaixo, uma amostra de como isto 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();
        }
    }

O redirecionamento para outra página também parece ser uma resposta razoável para a exceção.

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

A resposta a esta pergunta é simples:

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

Este iria desativar validação da solicitação particular.

Por favor, tenha em mente que alguns controles NET será automaticamente HTML codificar a saída. Por exemplo, definindo a propriedade .Text em um controle de caixa de texto irá codificá-lo automaticamente. Isso significa especificamente converter < em &lt;, > em &gt; e & em &amp;. Então, ser cauteloso em fazer isso ...

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

No entanto, a propriedade .Text para HyperLink, Literal e rótulo não HTML codificar as coisas, então Server.HtmlEncode embrulho (); torno de qualquer coisa sendo definido nessas propriedades é uma obrigação se você quer evitar <script> window.location = "http://www.google.com"; </script> de ser saída para a sua página e, posteriormente executado.

Faça um pouco de experimentar para ver o que é codificado eo que não funciona.

No arquivo web.config, dentro das marcas, inserir o elemento httpRuntime com o atributo requestValidationMode = "2.0". Além disso, adicione o validateRequest = atributo "false" no elemento de páginas.

Exemplo:

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

Se você não quiser desabilitar ValidateRequest você precisa 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, por trás do código, no evento PageLoad, adicione o atributo para o seu controle com o seguinte código:

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

Parece que ninguém tenha mencionado a seguir ainda, mas corrige o problema para mim. E antes que alguém diz sim, é Visual Basic ... eca.

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

Eu não sei se existem quaisquer desvantagens, mas para mim isso funcionou incrível.

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

Se você estiver usando framework 4.0, em seguida, a entrada no web.config ()

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

Se você estiver usando framework 4.5, em seguida, 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 única página, em seguida, em que você aspx arquivo que você deve colocar a primeira linha como esta:

<%@ Page EnableEventValidation="false" %>

Se você já tem algo como <% @ Page portanto basta adicionar o resto => EnableEventValidation="false"%>

Eu recomendo não fazê-lo.

Em ASP.NET, você pode capturar a exceção e fazer algo sobre isso, como exibir uma mensagem amigável ou redirecionamento para outra página ... Também há uma possibilidade de que você pode lidar com a validação por si mesmo ...

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

Eu acho que você poderia fazê-lo em um módulo; mas que deixa em aberto algumas questões; E se você quiser salvar a entrada para um banco de dados? De repente, porque você está salvando dados codificados para o banco de dados você acaba confiando entrada a partir dele que é provavelmente uma má idéia. Idealmente, você armazenar dados não codificados matérias no banco de dados ea codificação de cada vez.

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

Ao invés de usar Server.HtmlEncode você deve olhar para o mais recente, mais completa Anti-XSS biblioteca da equipe do Microsoft ACE.

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

  • Faça a caixa de texto de um elemento HTML (como textarea) em vez de um ASP.
  • Adicionar um campo escondido.
  • Adicione a seguinte função JavaScript para o seu cabeçalho.

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

Em seu textarea, incluir uma onchange que as chamadas boo ():

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

Finalmente, em .NET, use

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

Estou ciente de que este é um caminho - se você precisa de duas vias que você vai ter que ser criativo, mas isso fornece uma solução se você não pode editar o web.config

Aqui está um exemplo I (MC9000) veio com 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 tenta postar via ignorando JavaScript, que eles vão apenas ver o erro. Você pode salvar todos esses dados codificados em um banco de dados, bem como, em seguida, unescape-lo (no lado do servidor), e analisar e verificar a existência de ataques antes de exibir em outro lugar.

Causa

ASP.NET por padrão valida todos os controles de entrada para os conteúdos potencialmente perigosos que podem levar a cross-site scripting (XSS) e SQL injecções . Assim, não permite esse tipo de conteúdo por atirar a excepção acima. Por padrão é recomendado para permitir essa verificação para acontecer em cada nova postagem.

Solução

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

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

Isso irá desativar a validação de pedidos para a página que você definir o sinalizador ValidateRequest como falsa. Se você quiser desativar isso, verifique em sua aplicação web; você precisará configurá-lo para false no seu web.config

<pages validateRequest ="false" />

Para .NET 4.0 ou quadros superiores você precisará também adicionar a seguinte linha na seção para fazer o trabalho acima.

<httpRuntime requestValidationMode = "2.0" />

É isso. Espero que isso ajude você a se livrar do problema acima.

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

As outras soluções aqui são agradáveis, no entanto, é um pouco de uma dor real na parte traseira de ter de aplicar [AllowHtml] para cada propriedade modelo único, especialmente se você tem mais de 100 modelos em um site de tamanho decente.

Se gosta de mim, você quer transformar este (IMHO bastante inútil) recurso de fora do local de largura você pode substituir o método () no seu controlador de base Executar (se você não tiver um controlador de base que eu sugiro que você faça um, eles podem ser muito útil para aplicar a funcionalidade comum).

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

Apenas certifique-se que você é HTML codificar tudo o que é bombeado para fora para os pontos de vista que veio de entrada do usuário (é comportamento padrão no ASP.NET MVC 3 com navalha de qualquer maneira, a menos que por alguma razão bizarra que você está usando Html.Raw () você não deve precisar deste recurso.

Eu estava recebendo esse erro também.

No meu caso, um usuário entrou em uma á caractere acentuado em um papel Nome (sobre o provedor de associação ASP.NET).

eu passar o nome da função a um método para conceder aos usuários a esse papel eo pedido $.ajax pós estava falhando miseravelmente ...

Eu fiz isso para resolver o problema:

Em vez de

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

Faça isto

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

@Html.Raw fez o truque.

Eu estava recebendo o nome da função como valor HTML roleName="Cadastro b&#225;s". Este valor com &#225; entidade HTML estava sendo bloqueada pelo ASP.NET MVC. Agora eu entendo o valor do parâmetro roleName a forma como deve ser:. roleName="Cadastro Básico" e motor ASP.NET MVC não vai bloquear mais o pedido

Desativar a validação da página se você realmente precisa os caracteres especiais como, >, <, etc. Em seguida, garantir que, quando a entrada do usuário é exibido, os dados é codificado em HTML.

Existe uma vulnerabilidade de segurança com a validação da página, por isso pode ser contornado. Além disso, a validação da página não deve ser apenas invocada.

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

Você também pode usar fuga de JavaScript (string) função para substituir os caracteres especiais. Em seguida, use lado do servidor Server. URLDecode (string) para ligá-lo de volta.

Desta forma, você não tem que desligar a validação de entrada e será mais claro para outros programadores que a cadeia pode ter o conteúdo HTML.

Acabei usando JavaScript antes de cada nova postagem para verificar se os caracteres que você não deseja, tais 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;
}

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

Enquanto estes são apenas "<" e ">" (e não a própria aspa) caracteres e você estiver usando-os no contexto como , você está seguro (enquanto para você estaria vulnerável é claro). Isso pode simplificar a sua situação, mas para nada mais uso uma das outras soluções enviado.

Se você está olhando apenas para dizer a seus usuários que não devem ser usados, mas, você não quer que o formulário inteiro processado / não enviada de volta (e perder todas as entradas) antes da mão você poderia simplesmente colocar em um validador em torno do campo para a tela para aqueles (e talvez outras potencialmente perigosas) caracteres?

Nenhuma das sugestões funcionou para mim. Eu não queria desativar esse recurso para todo o website de qualquer forma, porque o tempo de 99% eu não quero que meus usuários colocar HTML em formulários web. Acabei de criar meu próprio método em torno do trabalho desde que eu sou o único a usar esta aplicação particular. Converter a entrada de HTML no código por trás e inseri-lo no meu banco de dados.

Você pode usar algo como:

var nvc = Request.Unvalidated().Form;

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top