Prevenindo ataques XSS em aplicações ASP.NET

Cross-site scripting (XSS) é um tipo de falha de segurança tipicamente encontrada em aplicações web que permite o atacante inserir código dentro das páginas visitadas pela vítima.

Uma das formas mais comuns de explorar esta vulnerabilidade é inserir um formulário web no site vulnerável para tentar obter informações valiosas da vítima.

Outro método é roubar os cookies de sessão do usuário para enviá-los ao atacante.

Exemplo de vulnerabilidade em uma aplicação:

http://www.dominio.com.br/shopping/produto.php?id=%3Cscript%3Ealert%28%22Hello%20XSS%22%29%3B%3C%2Fscript%3E

O trecho após o ?id= é o mesmo que “<script>alert(“Hello XSS”);</script>”, ou seja se a aplicação estiver vulnerável à ataques XSS, o código javascript inserido na URL seria executado.

>Mas alguém pode estar se perguntar da seguinte forma: “o que a minha aplicação tem a ver com isto? visto que ela não atinge meus servidores, mas sim o usuário?”

Respondendo a este questionamento, um ataque beem comum conhecido como Phishing onde por exemplo o atacante cria uma página falsa e envia os links por e-mail esperando alguém desatento clicar e fornecer os dados reais, veja exemplos de como este ataque pode ocorrer aqui.

Bom, mas sem delongas e vamos para a prática 🙂 pois o assunto é muito extenso.

Abra o Visual Studio (neste exemplo utilizei a versão 2010), e crie um novo projeto ASP.NET MVC chamado XSS conforme a imagem a seguir:

Criação do Projeto XSS - Visual Studio

Adicione um novo Controller chamado NewsletterController conforme as imagens abaixo:

Adição de Controller4-NewsletterController

Clique com o botão direito na pasta Models, e no menu selecione Add > New Class e adicione uma nova classe chamada Newsletter.

Na classe criada, insira o seguinte código:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web;

namespace XSS.Models
{
   public class Newsletter
   {
      public int Id { get; set; }
      [DisplayName("Title: ")]
      public string Title { get; set; }
      [DisplayName("Author: ")]
      public string Author { get; set; }
      [DisplayName("Summary: ")]
      public string Summary { get; set; }
      [DisplayName("News: ")]
      public string Content { get; set; }
    }
}

Já no nosso controller deixe da seguinte forma:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using XSS.Models;

namespace XSS.Controllers
{
    public class NewsletterController : Controller
    {
        //
        // GET: /Newsletter/

        public ActionResult Index()
        {
            Newsletter model = new Newsletter();
            return View(model);
        }

        [HttpPost]
        public ActionResult Add(Newsletter model)
        {
            // TODO: Your logic here
            TempData["News"] = model.Content;
            return RedirectToAction("Index", "Home");
        }

    }
}

Agora clique com o botão direito na linha return View(model); e selecione Add View conforme a imagem abaixo:
Adicionando View ao Projeto
Crie um formulário dentro da view da seguinte forma:


<h2>Index</h2>

@using(Html.BeginForm("Add", "Newsletter", FormMethod.Post))
{
<p>
@Html.LabelFor(m => m.Title)
@Html.TextBoxFor(m => m.Title)
</p>
<p>
@Html.LabelFor(m => m.Summary)
@Html.TextBoxFor(m => m.Summary)
</p>
<p>
@Html.LabelFor(m => m.Author)
@Html.TextBoxFor(m => m.Author)
</p>
<p>
@Html.LabelFor(m => m.Content)
@Html.TextAreaFor(m => m.Content)
</p>

<p>
<input type="submit" value="Send" />
</p>
}

Abra o arquivo Views/Home/Index.cshtml e insira o seguinte trecho para imprimir o conteúdo da notícia:


@if (TempData["News"] != null)
{
    @* Imprime o conteúdo do formulário *@
@Html.Raw(TempData["News"])
}

Agora pressione F5 para compilar e executar a aplicação, e preencha o formulário que está na url: http://localhost:<porta>/Newsletter, conforme exemplo abaixo:

Preenchimento dos dados
Preenchimento dos dados

Note que no campo News: coloquei um código javascript para explorar a vulnerabilidade no navegador;

Após o preenchimento dos campos. clique no botão Send para efetuar o post, aparecerá uma mensagem de erro semelhante à seguinte:

9-Erro_Post

As aplicações .NET por padrão tentam bloquear qualquer insersão de códigos em formulários justamente para evitar ataques XSS nas aplicações desenvolvidas, mas caso seja extremamente necessário postar códigos HTML, XML entre outros, este recurso pode ser desabilitado da seguinte forma:

Abra o código da classe NewsletterController e adicione a seguinte código acima do método Add(Newsletter model):


// ......

[ValidateInput(false)] // Adicione esta linha
public ActionResult Add(Newsletter model)
{
// continua o código
}

Após esta alteração, pressione F5 para executar novamente o projeto, preencha o formulário da mesma forma que foi feito anteriormente e veja o resultado:

Alerta exibido através de ataque XSS

Agora vamos corrigir esta falha de segurança:

  1. Clique no menu Tools > Library Package Manager > Package Manager Console
  2. Utilizando o Nugget vamos baixar a bibliteca AntiXSS digirando o comando Install-Package AntiXSS conforme imagem abaixo;Instalação AntiXSS Nugget
  3. No método Add do nosso controller, altere o corpo do método para que fique da seguinte forma:
    [HttpPost]
            [ValidateInput(false)]
            public ActionResult Add(Newsletter model)
            {
                // TODO: Your logic here
    
                // O método Sanitizer.GetSafeHtmlFragment(string input) remove todo conteúdo que está entre tags
                // impedindo desta forma boa parte dos ataques XSS
                string contentAntiXSS = Sanitizer.GetSafeHtmlFragment(model.Content);
                TempData["News"] = contentAntiXSS;
                return RedirectToAction("Index", "Home");
            }
                
  4. Coloque um breakpoint na linha TempData[“News”] para inspecionar o conteúdo da variável contentAntiXSS;
  5. Execute novamente o projeto e envie o formulário como nos testes anteriores.
  6. Veja a diferença após a remoção do trecho de código com o Sanitizer:13-Inspecao_Variaveis
  7. Pronto, ao completar a execução, o conteúdo é exibido sem nenhum risco na nossa página inicial.

Download do projeto: aqui (sem bibliotecas) ou aqui (com as bibliotecas)

Fico por aqui, até a próxima.

🙂

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s