Evitando ataques XSS em aplicativos ASP.NET

Um dos ataques mais comuns na Web é chamado de “Cross-Site Scripting” ou XSS. Ele consiste no envio de tags HTML contendo “scripts” que, ao serem executados, causam algum benefício ao atacante. Este benefício pode variar do roubo de algum cookie até a substituição do site visitado por um outro fajuto de forma a roubar informações como senhas e números de cartão de crédito.

Uma característica importante deste tipo de ataque é que o atacante tem que enviar o script de forma que ele seja executado por outro usuário (não há benefício algum se o script é executado apenas em uma página que apenas o próprio atacante tem acesso). Por causa disto, os sites mais vulneráveis a este tipo de ataque são aqueles no qual um usuário coloca informação que é lida por outros, como por exemplo:

  • Fórums de discussão;

  • Sites com diários ou “blogs”;

  • Sites que permitam avaliação de produtos;

  • Sites que aceitam comentários de forma geral.

Nesta página

Testando a vulnerabilidade
Defesa
Exibindo em TextBox
Conclusão

Testando a vulnerabilidade

Uma maneira de testar se um determinado site é vulnerável a este tipo de ataque é digitar um script em um campo texto e observar se este script é executado quando enviado de volta. Um exemplo de script seria “<script>alert('Te Peguei');</script>”. Um aplicativo vulnerável mostraria uma caixa de diálogo como mostrado a seguir:

Cc518054.xss1(pt-br,MSDN.10).gif

Felizmente o ASP.NET 1.1 (mas não o ASP.NET 1.0) normalmente impede esse comportamento. Se você tentar enviar uma tag HTML a um aplicativo ASP.NET 1.1, será disparada uma exception:

Cc518054.xss2(pt-br,MSDN.10).gif

Defesa

Mas o que devemos fazer se desejarmos aceitar tags HTML ou, pelo menos, o sinal de menor?

Bem, no ASP.NET 1.1, você deve colocar validateRequest = "false" na primeira linha do arquivo .aspx, como por exemplo:

%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="Segur1.WebForm1" validateRequest = "false" %

Note que o seu aplicativo ASP.NET 1.1 ficou vulnerável a ataques. Precisamos agora “neutralizar” o texto, de forma que ele não possa ser interpretado como tag HTML. Uma das maneiras de fazer isso é com o método Server. HtmlEncode . Este método substitui caracteres perigosos por uma seqüência de caracteres que é exibida pelo navegador corretamente, mas não é perigosa. Por exemplo, o sinal de menor vira &lt;”.

private void Button1_Click(object sender, System.EventArgs e)
{
Label1.Text = Server.HtmlEncode(TextBox1.Text);
}

Se você quiser então permitir a entrada de caracteres “perigosos”, recomendo então que você passe todos os caracteres de entrada pelo método HTMLEncode .

Exibindo em TextBox

O TextBox do ASP.NET tem uma característica um pouco estranha: ele chama o método HTMLEncode antes de exibir um texto. Isso significa que se você enviar ao TextBox um texto que já passou pelo método HTMLEncode , ele será codificado duas vezes, o que não é bom.

Uma das maneiras de evitar este comportamento é passar a string pelo método HTMLDecode antes de exibi-la em um TextBox.

Veja um exemplo de uma página ASP.NET ajustada para validateRequest = "false ". O primeiro TextBox é a entrada; o Label e o segundo TextBox apresentam a saída depois de passar por HTMLEncode e o texto do terceiro TextBox passou por HTMLDecode. Em nenhum caso o script rodou.

Cc518054.xss3(pt-br,MSDN.10).gif

O código associado ao click do botão no exemplo acima é o seguinte:

private void Button1_Click(object sender, System.EventArgs e)
{
string Msg = Server.HtmlEncode(TextBox1.Text);
Label1.Text = Msg;
TextBox2.Text = Msg;
TextBox3.Text = Server.HtmlDecode(Msg);
}

Conclusão

O ASP.NET 1.1 traz proteção contra ataques XSS, mas se você desejar permitir entradas de tags HTML, você deve chamar o método HTMLEncode.

Mauro Sant’Anna (mas_mauro@hotmail.com ) é MSDN Regional Director, INETA Speaker e escreve regularmente para diversos veículos e sites. Ele contribui regularmente para o site MSDN com artigos sobre segurança e bloga em http://br.thespoke.net/MyBlog/mauro/MyBlog.aspx .