Criando Páginas e Controles ASP.NET Seguros

Atualizado em: 20 de Maio de 2004
Nesta página
Neste móduloNeste módulo
ObjetivosObjetivos
AplicaçãoAplicação
Como usar este móduloComo usar este módulo
Ameaças e contramedidasAmeaças e contramedidas
Considerações sobre o projetoConsiderações sobre o projeto
Validação de entradasValidação de entradas
Cross–site scriptingCross–site scripting
AutenticaçãoAutenticação
AutorizaçãoAutorização
RepresentaçãoRepresentação
Dados confidenciaisDados confidenciais
Gerenciamento de sessãoGerenciamento de sessão
Manipulação de parâmetrosManipulação de parâmetros
Gerenciamento de exceçõesGerenciamento de exceções
Auditoria e logAuditoria e log
ResumoResumo
Recursos adicionaisRecursos adicionais

Neste módulo

As páginas da Web e os controles estão na linha de frente da defesa do seu aplicativo, podendo estar sujeitos a sondagens intensas por invasores que tentam comprometer a segurança do seu aplicativo. Geralmente, tais ataques têm como alvo sistemas e armazenamentos de dados back–end.

Um ataque bem–sucedido a um aplicativo, por exemplo, inclusão de código ou XSS (Cross–Site Scripting), explorará as vulnerabilidades dos aplicativos do servidor, o que pode ser devastador e levar a revelação de informações, spoofing de identidade, elevação de privilégios e execução de códigos remotos. Para criar páginas da Web e controles seguros, é preciso utilizar as devidas práticas de programação discutidas neste módulo.

Este módulo começa enumerando e explicando ameaças comuns a páginas e controles ASP.NET e as contramedidas associadas. Em seguida, será apresentada uma lista abrangente das áreas de segurança de aplicativos que devem ser consideradas. Isso inclui validação de entrada, codificação de saída, autenticação, autorização, representação, proteção de dados confidenciais, gerenciamento de sessão segura, proteção contra manipulação de parâmetros e gerenciamento de exceções. Essas técnicas são fundamentais para que a solução de segurança tenha uma defesa abrangente. As ameaças descritas, que são geralmente negligenciadas, permitem aos invasores comprometer seus sistema, independentemente do quanto sua infra–estrutura é segura.

Início da páginaInício da página

Objetivos

Use este módulo para:

Projetar páginas e controles ASP.NET seguros.

Desenvolver códigos de validação seguros usando expressões regulares e outras técnicas.

Impedir o XSS (Cross–Site Scripting).

Autenticar e autorizar seus usuários.

Desenvolver uma autenticação de formulários segura.

Impedir que informações detalhadas sobre exceções cheguem ao cliente.

Gerenciar e proteger suas seções ASP.NET.

Impedir a manipulação de parâmetros.

Saber quais contramedidas aplicar para impedir ameaças comuns, como inclusão de código, seqüestro de sessão, spoofing de identidade, manipulação de parâmetros, interceptação da rede, revelação de informações, XSS (Cross–Site Scripting) e ataques de repetição de cookie.

Início da páginaInício da página

Aplicação

Este módulo aplica–se aos produtos e às tecnologias a seguir:

Microsoft® Windows® 2000 Server e Microsoft Windows Server™ 2003.

Microsoft .NET Framework 1.1 e ASP.NET 1.1.

Início da páginaInício da página

Como usar este módulo

Além das práticas de programação seguras apresentadas, use os módulos correspondentes deste guia para criar páginas e controles ASP.NET seguros.

Implemente as etapas do, "Protegendo seus Aplicativos ASP.NET e Web Services". Este módulo ajuda a configurar o ASP.NET adequadamente com configurações seguras em Machine.config e Web.config.

Use a lista de verificação associada na seção de listas de verificação deste guia. A "Lista de verificação: protegendo o ASP.NET" reúne as recomendações deste módulo e do módulo 19. Certifique–se de implementar as orientações fornecidas.

Compreenda as ameaças e os ataques específicos de páginas e controles ASP.NET. Aplique as contramedidas de acordo com as diretrizes deste módulo.

Leia, "Diretrizes de Projeto para Proteger os Aplicativos da Web". Muitas das recomendações deste módulo (módulo 10) são baseadas nas diretrizes de projeto discutidas no módulo 4.

Os arquitetos devem usar a seção "Considerações sobre o projeto" deste módulo.

Os desenvolvedores devem aplicar as orientações deste módulo para seu processo de desenvolvimento. Os desenvolvedores devem prestar uma atenção especial na seção Validação de entradas, pois a maioria dos principais ataques a aplicativos dependem de vulnerabilidades nessa área.

Veja os controles do ponto de vista programático para adequar a segurança das páginas e controles ASP.NET.

Use as categorias de vulnerabilidade de aplicativos como uma maneira de impedir problemas comuns. Elas abordam e agrupam problemas de um jeito prático.

Início da páginaInício da página

Ameaças e contramedidas

A maioria dos ataques a aplicativos da Web solicitam a transmissão de entradas mal–intencionadas por meio de solicitações HTTP. O objetivo geral é coagir o aplicativo a executar operações não autorizadas ou interromper suas operações normais. É por isso que uma validação de entradas abrangente é uma contramedida essencial para vários ataques, devendo ser uma prioridade no desenvolvimento de páginas da Web e controles ASP.NET. Entre as principais ameaças, estão:

Inclusão de código.

Seqüestro de sessão.

Spoofing de identidade.

Manipulação de parâmetros.

Espionagem na rede.

Revelação de informações.

A figura 10.1 realça as ameaças mais comuns a aplicativos da Web.

Ameaças comuns a páginas da Web e controles ASP.NET

Figura 10.1
Ameaças comuns a páginas da Web e controles ASP.NET

Inclusão de código

A inclusão de código ocorre quando um invasor faz com que códigos arbitrários sejam executados usando o contexto de segurança do seu aplicativo. O risco é ainda maior se o seu aplicativo é executado usando uma conta privilegiada.

Ataques

Há quatro tipos de ataque de inclusão de código. Eles são:

Cross–site scripting. Um script mal–intencionado é enviado a um aplicativo da Web como uma entrada. Ele é ecoado de volta para o navegador de um usuário, no qual é executado.

Estouros do buffer. A verificação de digitação segura de códigos gerenciados reduz esse risco significativamente, mas ainda assim seu aplicativo estará vulnerável, especialmente nos pontos em que ele chamar códigos não gerenciados. Estouros do buffer podem permitir que um invasor execute códigos arbitrários dentro do processo do seu aplicativo da Web, usando seu contexto de segurança.

Inclusão de código SQL. Esse ataque tem como alvo códigos vulneráveis de acesso a dados. O invasor envia uma entrada de SQL que altera a consulta pretendida ou realiza consultas completamente novas no banco de dados. Páginas de logon para autenticação de formulários são alvos comuns, pois o nome de usuário e a senha são usados para fazer consultas no armazenamento de usuários.

Vulnerabilidades

As vulnerabilidades que permitem ataques de inclusão de código bem–sucedidos incluem:

Validação de entradas de vulnerável ou ausente, ou confiança no cliente para a validação de entradas.

Inclusão de entradas não validadas na saída de HTML.

Criação dinâmica de instruções SQL que não utilizam parâmetros digitados.

Uso de logon em contas e bancos de dados por meio de processos com excesso de privilégios.

Contramedidas

As contramedidas a seguir podem ser usadas para impedir a inclusão de código:

Validar as entradas para que os invasores não consigam incluir códigos de script ou causar estouros de buffer.

Codificar todos os dados de saída que incluam dados de entrada. Isso impede que marcas de scripts potencialmente mal–intencionadas sejam interpretadas como código pelo navegador do cliente.

Usar os procedimentos armazenados que aceitam parâmetros para impedir que entradas mal–intencionadas no SQL sejam tratadas pelo banco de dados como instruções executáveis.

Usar contas de representação e processos com menos privilégios. Isso reduz o risco e os danos que podem ser causados caso um invasor consiga executar códigos usando o contexto de segurança do aplicativo.

Seqüestro de sessão

O seqüestro de sessão ocorre quando o invasor captura um identificador de autenticação e adquire o controle da sessão de outro usuário. Geralmente, os identificadores de autenticação são armazenados em cookies ou URLs. Se o invasor capturar o identificador de autenticação, ele poderá transmiti–lo ao aplicativo com uma solicitação. O aplicativo associa a solicitação à sessão legítima do usuário, permitindo ao invasor obter acesso a áreas restritas do aplicativo que exigem acesso autenticado. Assim, o invasor assume a identidade e os privilégios do usuário legítimo.

Vulnerabilidades

As vulnerabilidades comuns que tornam suas páginas da Web e seus controles suscetíveis ao seqüestro de sessão incluem:

URLs contendo identificadores de sessão desprotegidos.

Mistura de cookies de personalização com cookies de autenticação.

Cookies de autenticação transmitidos por meio de links não criptografados.

Ataques

Os ataques de seqüestro de sessão incluem:

Repetição de cookie. O invasor captura o cookie de autenticação usando um software de monitoramento de rede ou outros meios, por exemplo, explorando a vulnerabilidade XSS.

Manipulação de seqüência de caracteres para consulta. Um usuário mal–intencionado altera o identificador de sessão, que é claramente visível na seqüência de caracteres para consulta da URL.

Contramedidas

Você pode empregar as seguintes contramedidas para impedir o seqüestro de sessão:

Usar cookies distintos para personalização e autenticação.

Transmitir cookies de autenticação apenas por meio de conexões HTTPS.

Não transmitir identificadores de sessão que representem usuários autenticados em seqüências de caracteres para consulta.

Fazer uma nova autenticação do usuário antes da realização de operações críticas, como substituição de pedidos, transferência de dinheiro, etc.

Spoofing de identidade

O spoofing de identidade ocorre quando um usuário mal–intencionado assume a identidade de um usuário legítimo para poder acessar o aplicativo.

Vulnerabilidades

As vulnerabilidades comuns que tornam suas páginas da Web e seus controles suscetíveis a ataques de spoofing de identidade incluem:

Credenciais de autenticação transmitidas por meio de links não criptografados.

Cookies de autenticação transmitidos por meio de links não criptografados.

Senhas e diretivas inconsistentes.

Armazenamento de credenciais de baixa segurança no armazenamento do usuário.

Ataques

Os ataques de spoofing de identidade incluem:

Repetição de cookie. O invasor rouba o cookie de autenticação usando um software de monitoramento de rede ou um ataque XSS. Em seguida, o invasor envia o cookie ao aplicativo para obter acesso por meio de falsificação.

Ataques agressivos de descoberta de senha. O invasor tenta repetidamente combinações de nome de usuário e senha.

Ataques de dicionário. Nesta forma automatizada de ataque agressivo de descoberta de senha, cada palavra de um dicionário é tentada como senha.

Contramedidas

Você pode empregar as seguintes contramedidas para impedir o spoofing de identidade:

Transmitir credenciais e cookies de autenticação apenas por meio de conexões HTTPS.

Aplicar senhas de alta segurança. Expressões regulares podem ser usadas para garantir que as senhas fornecidas pelo usuário atendam aos requisitos de complexidade apropriados.

Armazenar verificadores de senha no banco de dados. Armazenar hashes de senha não reversíveis combinados a um valor falso aleatório para reduzir o risco de ataques de dicionário.

Para obter mais informações sobre o armazenamento de hashes de senha e outros segredos do banco de dados, consulte o módulo 14, "Criando Acesso Seguro aos Dados".

Manipulação de parâmetros

Os parâmetros são itens de dados transmitidos do cliente para o servidor pela rede. Eles incluem campos de formulário, seqüência de caracteres para consulta, estado de exibição, cookies e cabeçalhos HTTP. Se dados confidenciais ou dados usados para tomar decisões de segurança no servidor forem transmitidos por meio de parâmetros desprotegidos, seu aplicativo estará potencialmente vulnerável à revelação de informações ou a acesso não autorizado.

Vulnerabilidades

As vulnerabilidades que podem levar à manipulação de parâmetros incluem:

Uso de campos de formulário ocultos ou seqüência de caracteres para consulta que contêm dados confidenciais.

Transmissão de cookies que contêm dados relacionados à segurança por conexões criptografadas.

Ataques

Os ataques de manipulação de parâmetros incluem:

Ataques de repetição de cookie. O invasor captura e altera um cookie e, em seguida, o repete para o aplicativo. Isso pode facilmente permitir o spoofing de identidade e a elevação de privilégios, caso o cookie contenha dados usados para autenticação ou autorização no servidor.

Manipulação de campos de formulário ocultos. Esses campos contêm dados usados para se tomar decisões de segurança no servidor.

Manipulação de parâmetros de seqüência de caracteres para consulta.

Contramedidas

Você pode empregar as seguintes contramedidas para impedir a manipulação de parâmetros:

Não depender das opções de gerenciamento de estado do cliente. Evite usar qualquer opção de gerenciamento de estado do cliente, como estado de exibição, cookies, seqüência de caracteres para consulta ou campos de formulário ocultos, para armazenar dados confidenciais.

Armazenar dados confidenciais no servidor. Use um identificador de sessão para associar a sessão do usuário a itens de dados confidenciais mantidos no servidor.

Usar um MAC (Código de Autenticação de Mensagem) para proteger o identificador de sessão. Complemente essas medidas com autenticação, autorização e lógica comercial no servidor para garantir que o identificador não esteja sendo repetido.

Espionagem na rede

A espionagem da rede envolve o uso de softwares de monitoramento de rede para rastrear pacotes de dados enviados entre o navegador e o servidor Web. Isso pode levar à revelação de dados confidenciais específicos do aplicativo, à recuperação de credenciais de logon ou à captura de cookies de autenticação.

Vulnerabilidades

As vulnerabilidades que podem levar a uma espionagem bem–sucedida da rede incluem:

Ausência de criptografia ao enviar dados confidenciais.

Envio de cookies de autenticação por canais não criptografados.

Ataques

Ataques de espionagem da rede são realizados com o uso de sniffers de pacote colocados na rede para capturar o tráfego.

Contramedidas

Para impedir a espionagem da rede, use o SSL (Secure Sockets Layer) para fornecer um canal de comunicação criptografado entre o navegador e o servidor Web. É imperativo que o SSL seja usado sempre que credenciais, permissões de autenticação ou dados confidenciais de aplicativos forem enviados pela rede.

Divulgação de informações

A revelação de informações ocorre quando um invasor investiga suas páginas da Web buscando meios para causar condições de exceção. Essa pode ser uma prática proveitosa para o invasor, pois os detalhes de exceção, que geralmente são retornados em HTML e exibidos no navegador, podem oferecer informações extremamente úteis, como rastreamentos de pilha que contêm seqüência de caracteres de conexão a banco de dados, nomes de bancos de dados, informações sobre o esquema do banco de dados, instruções SQL, bem como versão do sistema operacional e da plataforma.

Vulnerabilidades

As vulnerabilidades que podem levar à revelação de informações incluem:

Manipulação de exceção inconsistente.

Permitir que detalhes não processados sobre exceções se propaguem ao cliente.

Ataques

Há vários ataques que podem resultar em revelação de informações. Eles são:

Estouros do buffer.

Envio deliberado de entradas incorretas.

Contramedidas

Para impedir a revelação de informações:

Use uma manipulação de exceção estruturada.

Retorne páginas de erro genéricas ao cliente.

Use páginas de redirecionamento padrão que contêm mensagens de erro genéricas e sem muitos detalhes.

Início da páginaInício da página

Considerações sobre o projeto

Antes de desenvolver páginas da Web e controles, há várias questões importantes que você deve considerar ao fazer o projeto. Eis as principais considerações:

Use validação de entradas no servidor.

Particione seu site.

Considere a identidade usada para acesso a recursos.

Proteja credenciais e permissões de autenticação.

Falhe com segurança.

Considere a granularidade da autorização.

Coloque os controles da Web e os controles de usuário em conjuntos separados.

Coloque os códigos de acesso a recursos em um conjunto separado.

Usar validação de entradas no servidor

Ao fazer o projeto, identifique as diversas fontes de entrada de usuários que suas páginas da Web e seus controles processam. Isso inclui campos de formulário, seqüência de caracteres para consulta e cookies recebidos de usuários da Web, bem como dados de fontes de dados back–end. O usuário da Web está claramente além da fronteira de confiança do seu aplicativo, portanto, todas as suas entradas devem ser validadas no servidor. A menos que você possa confiar totalmente nos dados recuperados de fontes de dados back–end, eles também devem ser validados e corrigidos antes de serem enviados ao cliente. Certifique–se de que a sua solução não depende da validação do cliente, pois isso é facilmente ignorado.

Particionar seu site

O projeto do seu site deve fazer uma diferença clara entre áreas acessíveis ao público e áreas restritas que exigem acesso autenticado. Use subdiretórios separados abaixo do diretório raiz virtual do seu aplicativo para manter páginas restritas, por exemplo, funcionalidade check–out em um site de comércio eletrônico típico que exige acesso autenticado e transmite dados confidenciais, como números de cartão de crédito. Subdiretórios separados permitem aplicar segurança adicional (por exemplo, exigindo SSL) sem gerar sobrecarga de desempenho SSL em todo o site. Isso também permite diminuir os riscos de seqüestro de sessão com a restrição da transmissão de cookies de autenticação por conexões HTTPS. A figura 10.2 mostra um particionamento típico.

Um site particionado em áreas públicas e seguras

Figura 10.2
Um site particionado em áreas públicas e seguras

Observe que na figura 10.2, a subpasta restrita está configurada no IIS (Serviços de Informações da Internet) para exigir acesso SSL. O primeiro elemento <authorization> no Web.config permite que todos os usuários acessem a área pública, enquanto o segundo elemento impede que usuários não autenticados acessem o conteúdo de subpastas seguras e obriga a fazer logon.

Para obter mais informações sobre a restrição de cookies de autenticação para que eles sejam transmitidos apenas por conexões HTTPS, e sobre como navegar entre páginas restritas e não restritas, consulte "Usar URLs absolutas para navegação" em "Autenticação" neste módulo.

Considerar a identidade usada para acesso a recursos

Por padrão, aplicativos ASP.NET não representam, e a conta de processo ASPNET menos privilegiada é usada para executar aplicativos da Web ASP.NET e para acessar recursos. Recomenda–se a configuração padrão. Há vários casos em que você pode querer usar um contexto de segurança diferente para o Windows para o acesso a recursos. Eles são:

Hospedagem de vários aplicativos no mesmo servidor
Você pode utilizar o IIS para configurar cada aplicativo para usar uma conta de usuário da Internet anônima separada e, em seguida, permitir a representação. Assim, cada aplicativo possuirá uma identidade distinta para o acesso a recursos. Para obter mais informações sobre essa abordagem, consulte, "Hospedando Vários Aplicativos da Web".

Acesso a um recurso remoto com requisitos de autenticação específicos
Se precisar acessar um recurso remoto específico (por exemplo, um compartilhamento de arquivo) e recebeu uma determinada conta do Windows para esse fim, você pode configurar essa conta como uma conta de usuário da Web anônimo para o seu aplicativo. Em seguida, use a personalização programática antes de acessar o recurso remoto específico. Para obter mais informações, consulte "Representação" mais adiante neste módulo.

Proteger credenciais e permissões de autenticação

Seu projeto deve incluir proteção de credenciais e permissões de autenticação. As credenciais precisam ser protegidas caso sejam transmitidas pela rede e enquanto estiverem em armazenamentos persistentes, como os arquivos de configuração. As transmissões de permissão de autenticação pela rede devem ser protegidas, pois estão vulneráveis a seqüestro. A criptografia pode resolver o problema. SSL ou IPSec podem ser usados para proteger a transmissão de credenciais e permissões pela rede, e o DPAPI é uma boa solução para criptografar credenciais em arquivos de configuração.

Falhar com segurança

Se o seu aplicativo falhar com uma condição de exceção irrecuperável, certifique–se de que ele falhe com segurança para não deixar o sistema aberto. Certifique–se de que detalhes da exceção (valiosos para um usuário mal–intencionado) não se propaguem para o cliente e que, em vez disso, páginas de erro genéricas sejam retornadas. Planeje administrar os erros usando uma manipulação de exceção estruturada, em vez de confiar no método de códigos de erro.

Considerar a granularidade da autorização

Considere a granularidade da autorização que você usa nas partes autenticadas do seu site. Se você configurou um diretório para exigir autenticação, todos os usuários devem ter acesso equivalente às páginas desse diretório? Se necessário, aplique diferentes regras de autorização para páginas separadas, com base na identidade ou, o que é mais comum, com base na participação da função do chamador, usando vários elementos <authorization> em elementos <location> separados.

Por exemplo, duas páginas no mesmo diretório podem ter elementos <allow> e <deny> diferentes no Web.config.

Colocar controles da Web e controles de usuário em conjuntos separados

Quando controles da Web e de usuário são colocados em seus próprios conjuntos, é possível configurar a segurança para cada conjunto independentemente, usando uma política de segurança de código de acesso. Isso proporciona flexibilidade adicional para o administrador e significa que você não é obrigado a conceder mais permissões a todos os controles apenas para satisfazer os requisitos de um único controle.

Colocar os códigos de acesso a recursos em um conjunto separado

Use conjuntos separados e chame–os a partir das suas classes de página, em vez de integrar o código de acesso a recursos nos manipuladores de evento da sua classe de página. Isso proporciona maior flexibilidade para a política de segurança de acesso a código e é particularmente importante para criar aplicativos da Web parcialmente confiáveis. Para obter mais informações, consulte, "Usando a Segurança do Acesso ao Código com o ASP.NET".

Início da páginaInício da página

Validação de entradas

Se você fizer suposições infundadas sobre o tipo, o tamanho, o formato ou o intervalo das entradas, é provável que seu aplicativo não seja robusto. A validação de entradas pode se tornar um problema de segurança se um invasor descobrir que você fez suposições infundadas. O invasor pode, então, fornecer entradas cuidadosamente preparadas para comprometer seu aplicativo. A confiança inadequada em entradas de usuário é uma das vulnerabilidades mais comuns e devastadoras dos aplicativos da Web.

Restringir e corrigir

Comece restringindo entradas e verifique os dados confiáveis conhecidos validando tipo, tamanho, formato e intervalo. Às vezes, você também precisará corrigir entradas e tornar seguras entradas potencialmente mal intencionadas. Por exemplo, se o seu aplicativo suporta campos de entrada em qualquer formato, como campos de comentários, você pode querer permitir certos elementos HTML "seguros", como <b> e <i>, e desfazer–se de quaisquer outros elementos HTML. A tabela a seguir resume as opções disponíveis para restringir e corrigir dados:

Tabela 10.1 Opções para restringir e corrigir dados

RequisitoOpções

Verificações de tipo

Sistema de tipo .NET Framework. Analise os dados da seqüência de caracteres, faça a conversão para um tipo de alta segurança e, em seguida, manipule as FormatExceptions.
Expressões regulares. Use o controle RegularExpressionValidator ASP.NET ou a classe Regex.

Verificações de tamanho

Expressões regulares
Propriedade String.Length

Verificações de formato

Expressões regulares para o padrão correspondente
Sistema de tipo .NET Framework

Verificações de intervalo

Controle RangeValidator ASP.NET (suporta moeda, data, números inteiros, duplicação e dados de seqüência de caracteres)
Comparações de dados digitados

Expressões regulares

Você pode usar expressões regulares para restringir o intervalo de caracteres válidos, para desfazer–se de caracteres indesejados e para realizar verificações de tamanho e formato. Você pode restringir o formato da entrada de dados, definindo os padrões aos quais a entrada deve corresponder. O ASP.NET oferece o controle RegularExpressionValidator, e a classe Regex está disponível a partir do espaço para nome System.Text.RegularExpressions.

Se você usar os controles de validação, a validação ocorrerá apenas se o controle estiver vazio. Para campos obrigatórios, use um RequiredFieldValidator. Além disso, há uma leve diferença entre a implementação da validação de expressões regulares no cliente e no servidor. No cliente, usa–se a sintaxe da expressão regular do software de desenvolvimento Microsoft JScript. No servidor, usa–se a sintaxe System.Text.RegularExpressions.Regex. Uma vez que a sintaxe de expressão regular JScript é um subconjunto da sintaxe System.Text.RegularExpressions.Regex, recomenda–se que a sintaxe da expressão regular JScript seja usada para produzir os mesmos resultados no cliente e no servidor.

Para obter mais informações sobre os controles de validação ASP.NET, consulte a documentação do .NET Framework.

Controle RegularExpressionValidator

Para validar a entrada de campo do formulário da Web, você pode usar o controle RegularExpressionValidator. Arraste o controle para uma formulário da Web e defina suas propriedades ValidationExpression, ControlToValidate e ErrorMessage.

É possível definir a expressão de validação usando a janela de propriedades do Microsoft Visual Studio® .NET ou definir as propriedades dinamicamente no manipulador de eventos Page_Load. A última abordagem permite agrupar todas as expressões regulares para todos os controles da página.

Classe Regex

Se você usar controles HTML regulares sem nenhuma propriedade runat="server" (a qual rege o uso do controle RegularExpressionValidator) ou se precisar validar entradas a partir de outras fontes, por exemplo, seqüência de caracteres para consulta ou cookies, é possível usar a classe Regex na classe da sua página ou em um método auxiliar de validação, possivelmente em um conjunto separado. Alguns exemplos são mostrados mais adiante nesta seção.

Comentários sobre expressões regulares

Expressões regulares são muito mais fáceis de compreender se você usar a sintaxe a seguir e comentar cada componente da expressão usando #. Para permitir comentários, você também deve especificar o RegexOptions.IgnorePatternWhitespace, o que significa que o espaço em branco não seguido é ignorado.

Regex regex = new Regex(@" 
                        ^           # anchor at the start 
                       (?=.*\d)     # must contain at least one digit 
                       (?=.*[a-z])  # must contain one lowercase 
                       (?=.*[A-Z])  # must contain one uppercase 
                       .{8,10}      # From 8 to 10 characters in length 
                       $            # anchor at the end",  
                       RegexOptions.IgnorePatternWhitespace);

Campos de seqüência de caracteres

Para validar os campos de seqüência de caracteres, como nomes, endereços, números de identificação de imposto, e assim por diante, use expressões regulares para fazer o seguinte:

Restringir o intervalo aceitável de caracteres de entrada.

Aplicar regras de formatação. Por exemplo, campos baseados em padrão, como números de identificação de imposto, CEP ou códigos postais, exigem padrões específicos de caracteres de entrada.

Verificar o tamanho.

Nomes

O exemplo a seguir mostra um controle RegularExpressionValidator usado para validar um campo de nome.

<form id="WebForm" method="post" runat="server"> 
  <asp:TextBox id="txtName" runat="server"></asp:TextBox> 
  <asp:RegularExpressionValidator id="nameRegex"runat="server"  
        ControlToValidate="txtName"  
        ValidationExpression="^[a-zA-Z'.`-´\s]{1,40}$"  
        ErrorMessage="Invalid name"> 
  </asp:regularexpressionvalidator> 
</form> 

A expressão de validação anterior limita o campo de nome de entrada a caracteres alfabéticos (letras minúsculas e maiúsculas), ao apóstrofo único para nomes, como O'Dell, e ao ponto. Além disso, o tamanho do campo é restrito a 40 caracteres.

Números da previdência social

O exemplo a seguir mostra o código HTML gerado para um controle RegularExpressionValidator usado para validar um campo de formulário destinado ao número da previdência social nos EUA:

<form id="WebForm" method="post" runat="server"> 
  <asp:TextBox id="txtSSN" runat="server"></asp:TextBox> 
  <asp:RegularExpressionValidator id="ssnRegex" runat="server"  
       ErrorMessage="Invalid social security number"  
       ValidationExpression="\d{3}-\d{2}-\d{4}"  
       ControlToValidate="txtSSN"> 
  </asp:RegularExpressionValidator> 
</form> 

A expressão de validação anterior é uma das expressões padrão que o Visual Studio .NET oferece. Ele valida o formato do campo de entrada fornecido, bem como seu tipo e tamanho. A entrada deve consistir em três dígitos numéricos, seguidos por um traço, em seguida, dois dígitos seguidos por um traço e, depois, quatro dígitos.

Se não estiver usando os controles do servidor (os quais regem os controles de validação) ou se precisar validar entradas de fontes que não sejam campos de formulários, é possível usar a classe System.Text.RegularExpression.Regex no código do seu método. O exemplo a seguir mostra como validar o mesmo campo usando um método estático Regex.IsMatch diretamente na classe de página, em vez de usar um controle de validação:

if (!Regex.IsMatch(txtSSN.Text, @"^\d{3}-\d{2}-\d{4}$")) 
{ 
  // Invalid Social Security Number 
}

Campos de data

Campos de entrada que possuem um tipo .NET Framework equivalente podem ser verificados pelo sistema de tipo .NET Framework. Por exemplo, para validar uma data, você pode converter o valor da entrada em uma variável de tipo System.DateTime e manipular quaisquer exceções de formato resultantes se os dados de entrada não forem compatíveis, como segue.

try 
{ 
  DateTime dt = DateTime.Parse(txtDate.Text).Date; 
} 
// If the type conversion fails, a FormatException is thrown 
catch( FormatException ex ) 
{ 
  // Return invalid date message to caller 
} 

Além de verificações de formato e tipo, pode ser preciso realizar uma verificação de intervalo em um campo de data. Isso pode ser feito facilmente com o uso da variável DateTime, como segue.

// Exception handling is omitted for brevity 
  DateTime dt = DateTime.Parse(txtDate.Text).Date; 
  // The date must be today or earlier 
  if ( dt > DateTime.Now.Date ) 
    throw new ArgumentException("Date must be in the past");

Campos numéricos

Se precisar validar dados numéricos, por exemplo, uma idade, realize verificações de tipo usando o tipo int. Para converter uma entrada de seqüência de caracteres para o formulário de número inteiro, use Int32.Parse ou Convert.ToIn32 e, em seguida, manipule qualquer FormatException que ocorrer com um tipo de dado inválido, como segue:

try 
{ 
  int i = Int32.Parse(txtAge.Text); 
  . . . 
} 
catch( FormatException) 
{ 
 . . . 
}

Verificações de intervalo

Às vezes, você precisa validar a entrada para que a data esteja em um intervalo pré–determinado. O código a seguir usa um controle ASP.NET RangeValidator para restringir a entrada a números inteiros entre 0 e 255. Este exemplo também usa o RequiredFieldValidator. Sem o RequiredFieldValidator, os outros controles de validação aceitam entradas em branco.

<form id="WebForm3" method="post" runat="server"> 
  <asp:TextBox id="txtNumber" runat="server"></asp:TextBox> 
  <asp:RequiredFieldValidator  
       id="rangeRegex"  
       runat="server"  
       ErrorMessage="Please enter a number between 0 and 255"  
       ControlToValidate="txtNumber" 
       style="LEFT: 10px; POSITION: absolute; TOP: 47px" > 
  </asp:RequiredFieldValidator> 
  <asp:RangeValidator  
       id="RangeValidator1"  
       runat="server"  
       ErrorMessage="Please enter a number between 0 and 255"  
       ControlToValidate="TextBox1"  
       Type="Integer"  
       MinimumValue="0" 
       MaximumValue="255"  
       style="LEFT: 10px; POSITION: absolute; TOP: 47px" > 
  </asp:RangeValidator> 
  <asp:Button id="Button1" style="LEFT: 10px; POSITION: absolute; TOP: 100px"  
              runat="server" Text="Button"></asp:Button> 
</form> 

O exemplo a seguir mostra como validar intervalos usando a classe Regex:

try 
{ 
  // The conversion will raise an exception if not valid. 
  int i = Convert.ToInt32(sInput); 
  if ((0 <= i && i <= 255) == true) 
  { 
    // data is valid, use the number 
  } 
} 
catch( FormatException ) 
{ 
  . . . 
} 

Corrigindo entradas

Corrigir significa tornar seguros dados potencialmente mal–intencionados. Pode ser útil quando o intervalo de entradas não permitido não pode garantir que a entrada seja segura. Isso pode incluir a eliminação de um item nulo a partir do final de uma seqüência de caracteres fornecida pelo usuário ou ignorar valores para que eles sejam tratados como literais. Se você não precisar corrigir entradas e converter ou desfazer–se de caracteres de entradas específicas, use o Regex.Replace.

Observação: use essa abordagem para uma defesa em profundidade. Sempre comece restringindo a entrada ao conjunto de valores "válidos" conhecidos.

O código a seguir elimina um intervalo de caracteres potencialmente não seguros, inclusive <>\"'%;()&.

private string SanitizeInput(string input) 
{ 
  Regex badCharReplace = new Regex(@"^([<>""'%;()&])$"); 
  string goodChars = badCharReplace.Replace(input, ""); 
  return goodChars; 
} 

Para obter mais informações sobre como corrigir campos de entrada de formato livre, como campos de comentários, consulte "Corrigindo entradas de formato livre" em "Cross–site scripting", mais adiante neste módulo.

Validando controles HTML

Se você não usa controles de servidor, ou seja, controles com o atributo runat="server", e, em vez disso, usa controles HTML regulares, não é possível usar os controles de validação ASP.NET. Em vez disso, você pode validar o conteúdo das suas páginas da Web usando expressões regulares no manipulador de eventos Page_Load, como segue.

using System.Text.RegularExpressions; 
. . . 
private void Page_Load(object sender, System.EventArgs e) 
{ 
  // Note that IsPostBack applies only for  
  // server forms (with runat="server") 
  if ( Request.RequestType == "POST" ) // non-server forms 
  { 
    // Validate the supplied email address 
    if( !Regex.Match(Request.Form["email"],  
         @"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$", 
         RegexOptions.None).Success)  
    { 
      // Invalid email address 
    } 
    // Validate the supplied name 
    if ( !RegEx.Match(Request.Form["name"], 
         @"^[A-Za-z'\- ]$", 
         RegexOptions.None).Success)  
    { 
      // Invalid name 
    } 
  } 
} 

Validando as entradas usadas para acesso a dados

Se estiver gerando consultas SQL dinâmicas com base em entradas do usuário, um ataque de inclusão de código SQL pode injetar comandos SQL mal–intencionados que podem ser executados pelo banco de dados. Em um cenário típico de acesso a dados baseado na Web, pode ser usada a seguinte estratégia de defesa em profundidade:

Use expressões regulares para restringir as entradas na sua classe de página.

Corrija ou recuse a entrada. Para uma defesa em profundidade, você pode optar por usar um método auxiliar para distribuir caracteres nulos ou outros caracteres incorretos conhecidos.

Use procedimentos armazenados parametrizados para acesso a dados para garantir que as verificações de tipo e tamanho sejam realizadas nos dados usados em consultas SQL.

Para obter mais informações sobre o uso de parâmetros para acesso a dados e sobre a gravação de código de acesso seguro a dados, consulte, "Criando Acesso Seguro aos Dados".

Validando as entradas usadas para E/S de arquivos

No geral, você deve evitar gravar códigos que aceitam a entrada de arquivos ou caminhos pelo chamador. Em vez disso, use nomes de arquivo e localizações fixos ao ler e gravar dados. Isso garante que seu código não será coagido a acessar arquivos arbitrários e que ele não esteja vulnerável a erros de padronização.

Se você não precisar aceitar nomes de arquivos de entrada, há dois principais desafios. Em primeiro lugar, o caminho do arquivo e o nome resultantes são um nome válido de sistema de arquivos? Em segundo lugar, o caminho é válido no contexto do seu aplicativo? Por exemplo, está abaixo da raiz do diretório virtual do aplicativo?

Para padronizar nomes de arquivo, use System.IO.Path.GetFullPath. Para verificar se o caminho do arquivo é válido no contexto do seu aplicativo, você pode usar a segurança de acesso ao código .NET para conceder o FileIOPermission preciso ao seu código, para que ele só consiga acessar arquivos a partir de diretórios específicos. Para obter mais informações, consulte as seções "E/S de arquivos", "Criando Conjuntos Seguros" e no, "Segurança do Acesso ao Código na Prática".

Usando o MapPath

Se você usar o MapPath para mapear um caminho virtual fornecido para um caminho físico no servidor, use a sobrecarga de Request.MapPath que aceita um parâmetro bool para evitar o mapeamento entre aplicativos, como segue:

try 
{ 
  string mappedPath = Request.MapPath( inputPath.Text,  
                                       Request.ApplicationPath, false); 
} 
catch (HttpException) 
{ 
  // Cross-application mapping attempted 
} 

O parâmetro final false impede o mapeamento entre aplicativos. Isso significa que um usuário não pode fornecer com êxito um caminho que contenha ".." para se desviar da hierarquia de diretório virtual do seu aplicativo. Qualquer tentativa em fazê–lo resulta em uma exceção do tipo HttpException.

Observação: os controles do servidor podem usar o método Control.MapPathSecure para ler arquivos. Esse método exige que seja concedida confiança total ao código de chamada pela diretiva de segurança de acesso, caso contrário, será gerada uma exceção HttpException. Para obter mais informações, consulte Control.MapPathSecure na documentação do .NET Framework SDK.

Expressões regulares comuns

O Visual Studio .NET oferece um conjunto útil de expressões regulares. Para acessá–las, adicione um controle RegularExpresssionValidator a um formulário da Web e clique no botão de reticências no campo da propriedade Expressão do controle. A tabela a seguir mostra várias expressões adicionais úteis para campos de página da Web comumente usados.

Tabela 10.2 Campos de expressões regulares úteis

Campo ExpressãoFormato de exemploDescrição

Nome

[a-zA-Z'`-´\s]{1,40}

John DoeO'Dell

Valida nomes. Permite até 40 caracteres em letra maiúscula e minúscula e alguns caracteres especiais comuns em alguns nomes. Essa lista pode ser adaptada.

Números

^\D?(\d{3})\D?\D?(\d{3})\D?(\d{4})$

(425)–555–0123
425–555–0123
425 555 0123

Valida números de telefone dos Estados Unidos.

Email

\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

alguem@exemplo.com

Valida endereços de email.

URL

^(http|https|ftp)\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(:[a-zA-Z0-9]*)?/?([a-zA-Z0-9\-\._\?\,\'/\\\+&%\$#\=~])*$

 

Valida URLs.

CEP

^(\d{5}-\d{4}|\d{5}|\d{9})$|^([a-zA-Z]\d[a-zA-Z] \d[a-zA-Z]\d)$

 

Valida CEPs dos Estados Unidos, permitindo 5 ou 9 dígitos.

Senha

^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$

 

Valida senhas de alta segurança. Deve ter de 8 a 10 caracteres e conter uma combinação de letras maiúsculas e minúsculas e dígitos numéricos, sem caracteres especiais.

Números inteiros não negativos

\d+

0986

Valida números inteiros maiores que zero.

Moeda (não negativo)

"\d+(\.\d\d)?"

 

Valida valores positivos em moeda. Exige dois dígitos após o ponto decimal.

Moeda (positivo ou negativo)

"(-)?\d+(\.\d\d)?"

 

Valida valores positivos ou negativos em moeda. Exige dois dígitos após o ponto decimal.

Início da páginaInício da página

Cross–site scripting

Os ataques XSS exploram vulnerabilidades na validação de páginas da Web por meio de inclusão de códigos de script no cliente. Esse código é subseqüentemente enviado de volta para um usuário e executado pelo navegador, sem que ele perceba. Uma vez que o navegador baixa o código de script a partir de um site confiável, ele não tem como identificar que o código não é legítimo, e as zonas de segurança do Internet Explorer não podem se defender. Os ataques XSS também funcionam por conexões HTTP ou HTTPS (SSL). Uma das explorações mais sérias ocorrem quando um invasor grava um script para recuperar o cookie de autenticação que oferece acesso ao site confiável e o publica em um endereço da Web conhecido pelo invasor. Isso permite ao invasor falsificar a identidade do usuário legítimo e conseguir acesso ilícito ao site.

Use as seguintes contramedidas para impedir ataques XSS:

Valide as entradas

Codifique as saídas

Validar as entradas

Valide o tipo, tamanho, formato e intervalo de qualquer entrada que não esteja dentro dos limites de confiança do seu aplicativo, usando as diversas técnicas descritas anteriormente neste módulo.

Codificar as saídas

Se você grava saída de texto em uma página da Web e não sabe com certeza absoluta se o texto contém caracteres especiais HTML (como <, > e &), então, certifique–se de processá–lo previamente usando o método HttpUtility.HtmlEncode. Faça isso mesmo se o texto é proveniente de uma entrada de usuário, banco de dados ou arquivo local. Do mesmo modo, use o HttpUtility.UrlEncode para codificar seqüências de caracteres de URL.

O método HtmlEncode substitui caracteres que possuem um significado especial em HTML pelas variáveis HTML que os representam. Por exemplo, < é substituído por < e " por ". Dados codificados não fazem com que o navegador execute códigos. Em vez disso, os dados são entregues como dados HTML inofensivos.

Response.Write(HttpUtility.HtmlEncode(Request.Form["name"])); 

Controles de dados vinculados

Controles da Web com dados vinculados não codificam as saídas. O único controle que codifica saídas é o TextBox quando sua propriedade TextMode é definida como MultiLine. Se você vincula qualquer outro controle a dados que possuem códigos XSS mal–intencionados, o código será executado no cliente. Como resultado, se você recuperar dados de um banco de dados e não puder ter certeza de que eles são válidos (talvez por que o banco de dados é compartilhado com outros aplicativos), codifique os dados antes de transmiti–los de volta ao cliente.

Corrigindo entradas de formato livre

Se sua página da Web inclui caixas destinadas a texto de formato livre, como o campo "comentários", nas quais você deseja permitir certos elementos HTML seguros, como <b> e <i>, é possível administrar isso com segurança primeiramente pré–processando com HtmlEncode e, em seguida, removendo seletivamente a codificação dos elementos permitidos, como segue:

StringBuilder sb = new StringBuilder( HttpUtility.HtmlEncode(userInput) ) ; 
sb.Replace("<b>", "<b>"); 
sb.Replace("</b>", "</b>"); 
sb.Replace("<i>", "<i>"); 
sb.Replace("</i>", "</I>"); 
Response.Write(sb.ToString()); 

Contramedidas de defesa em profundidade

Além das técnicas discutidas anteriormente, use as seguintes contramedidas de defesa em profundidade para impedir ataques XSS:

Defina a codificação de caractere correta.

Use a opção validateRequest do ASP.NET versão 1.1.

Instale o URLScan no seu servidor Web.

Use a opção de cookie HttpOnly.

Use o atributo de segurança <frame>.

Use a propriedade innerText.

Definir a codificação de caractere correta

Para restringir com êxito quais dados são válidos para suas páginas da Web, é importante limitar o modo como os dados de entrada podem ser representados. Isso impede que usuários mal–intencionados usem a padronização e seqüências de escape de vários bytes para enganar suas rotinas de validação de entradas.

O ASP.NET permite especificar o conjunto de caracteres no nível da página ou do aplicativo usando o elemento <globalization> no Web.config. Ambas as abordagens são mostradas abaixo usando a codificação de caractere ISO–8859–1, que é o padrão em versões anteriores de HTML e HTTP.

Para definir a codificação de caractere no nível da página, use o elemento <meta> ou o atributo de nível de página ResponseEncoding, como segue:

<meta http-equiv="Content Type"  
      content="text/html; charset=ISO-8859-1" /> 

OR

<% @ Page ResponseEncoding="ISO-8859-1" %> 

Para definir a codificação de caractere no Web.config, use a seguinte configuração:

<configuration> 
   <system.web> 
      <globalization  
         requestEncoding="ISO-8859-1" 
         responseEncoding="ISO-8859-1"/> 
   </system.web> 
</configuration> 

Validando caracteres Unicode

Use os códigos a seguir para validar caracteres Unicode em uma página:

using System.Text.RegularExpressions; 
. . . 
private void Page_Load(object sender, System.EventArgs e) 
{ 
  // Name must contain between 1 and 40 alphanumeric characters 
  // together with (optionally) special characters '`´ for names such 
  // as D'Angelo 
  if (!Regex.IsMatch(Request.Form["name"], @"^[\p{L}\p{Zs}\p{Lu}\p{Ll}]{1,40}$")) 
    throw new ArgumentException("Invalid name parameter"); 
  // Use individual regular expressions to validate other parameters 
  . . . 
} 

Segue uma explicação das expressões regulares mostradas no código anterior:

{<name>} especifica uma classe de caractere Unicode nomeada.

\p{<name>} corresponde a qualquer caractere na classe de caractere nomeada especificada por {<name>}.

{L} realiza uma correspondência da esquerda para a direita.

{Lu} realiza uma correspondência de letras maiúsculas.

{Ll} realiza uma correspondência de letras minúsculas.

{Zs} corresponde a separador e espaço.

{1,40} significa de 1 a 40 caracteres.

{Mn} corresponde a marcas e caracteres sem espaçamento.

{Zs} corresponde a separador e espaço.

* especifica zero ou mais correspondências.

$ nesse contexto, representa um ponto.

Usar a opção validateRequest do ASP.NET

O atributo validateRequest é um recurso do .NET Framework versão 1.1. Esse atributo é definido como verdadeiro por padrão no elemento <pages> no Machine.config. Ele instrui o ASP.NET a examinar todos os dados recebidos do navegador em busca de entradas potencialmente mal intencionadas, por exemplo, entradas que contêm elementos <script>. O ASP.NET examina entradas recebidas de campos de formulário HTML, cookies e seqüências de caracteres para consulta. O .NET Framework versão 1.0 não oferece nenhuma funcionalidade equivalente, mas o filtro URLScan ISAPI (Internet Server Application Programming Interface) do IIS pode executar uma tarefa semelhante. Também é possível aplicar a configuração a cada página usando a marca @ Page, como segue:

<% @ Page validateRequest="True" %> 

Instalar o URLScan no seu servidor Web

O URLScan é um filtro ISAPI instalado quando você executa a ferramenta IISLockdown. Isso ajuda a minimizar a ameaça de ataques XSS com a rejeição de entradas potencialmente mal intencionadas. Para obter mais informações sobre o IISLockdown e o URLScan, consulte, "Protegendo seu Servidor Web".

Observação: o IIS 6.0 no Windows Server 2003 tem funcionalidade equivalente ao URLScan integrado.

Usar a opção de cookie HttpOnly

O Internet Explorer 6 Service Pack 1 suporta um novo atributo de cookie HttpOnly, que impede que scripts do cliente acessem o cookie a partir da propriedade document.cookie. Em vez disso, é retornada uma seqüência de caracteres vazia. O cookie é enviado ao servidor sempre que o usuário navegar em um site da Web no domínio atual.

Observação: os navegadores da Web que não suportam o atributo de cookie HttpOnly ignoram o cookie ou o atributo, o que significa que ele ainda está sujeito a ataques XSS.

No momento, a classe System.Net.Cookie não suporta uma propriedade HttpOnly. Para adicionar um atributo HttpOnly ao cookie, você precisa usar um filtro ISAPI ou, se desejar uma solução de código gerenciado, adicione o código a seguir ao manipulador de eventos Application_EndRequest do seu aplicativo no Global.asax:

protected void Application_EndRequest(Object sender, EventArgs e)  
{ 
  string authCookie = FormsAuthentication.FormsCookieName; 
  foreach (string sCookie in Response.Cookies)  
  { 
    // Just set the HttpOnly attribute on the Forms authentication cookie 
    // Skip this check to set the attribute on all cookies in the collection 
    if (sCookie.Equals(authCookie)) 
    {  
      // Force HttpOnly to be added to the cookie header 
      Response.Cookies[sCookie].Path += ";HttpOnly"; 
    } 
  } 
} 

Observação: é provável que uma versão futura do .NET Framework tenha uma propriedade HttpOnly na classe Cookie.

Usar o atributo de segurança <frame>

O Internet Explorer 6 ou mais recente suporta um novo atributo de segurança nos elementos <frame> e <iframe>. Você pode usar o atributo security para aplicar configurações à zona de segurança Sites restritos do Internet Explorer do usuário em um frame individual ou iframe. Por padrão, a zona Sites restritos não suporta a execução de scripts. Se você usar o atributo security, ele deve estar definido como "restricted", como mostrado abaixo:

<frame security="restricted" src="http://www.somesite.com/somepage.htm"></frame> 

Usar a propriedade innerText

Se você criar uma página com entradas não confiáveis, use a propriedade innerText em vez de innerHTML. A propriedade innerText entrega conteúdo seguro e garante que nenhum script seja executado.

Início da páginaInício da página

Autenticação

Uma autenticação de baixa segurança aumenta o risco da ameaça de falsificação de identidade. Se as credenciais de logon de um usuário caírem nas mãos erradas, um invasor pode falsificar a identidade do usuário e obter acesso ao aplicativo. O invasor compartilhará todos os privilégios do usuário no aplicativo. As credenciais devem ser protegidas conforme são transmitidas pela rede e enquanto forem persistentes, por exemplo, no armazenamento de usuários do aplicativo. O cookie de autenticação que representa uma identidade autenticada para o aplicativo após o logon inicial também deve ser protegido para diminuir o risco de seqüestro de sessão e ataques de repetição de cookie.

Autenticação de formulários

A ameaça de seqüestro de sessão e de ataques de repetição de cookie é particularmente significativa para aplicativos que usam a Autenticação de formulários. É preciso um cuidado extra ao consultar o banco de dados usando credenciais fornecidas pelo usuário para garantir que você não esteja vulnerável à inclusão de código SQL. Além disso, para impedir a falsificação de identidade, você deve certificar–se de que o armazenamento de usuários esteja seguro e de que senhas de alta segurança sejam aplicadas.

O fragmento a seguir mostra uma configuração "segura" de Autenticação de formulários no Web.config:

  <forms loginUrl="Restricted\login.aspx"  Login page in an SSL protected folder 
         protection="All"                  Privacy and integrity 
         requireSSL="true"                 Prevents cookie being sent over http 
         timeout="10"                      Limited session lifetime 
         name="AppNameCookie"              Unique per-application name 
         path="/FormsAuth"                    and path 
         slidingExpiration="true" >        Sliding session lifetime 
  </forms> 

As recomendações a seguir o ajudarão a criar uma solução segura de Autenticação de formulários:

Particione seu site.

Proteja páginas restritas com SSL.

Use a autorização de URL.

Proteja o cookie de autenticação.

Use URLs absolutas para navegação.

Use um gerenciamento seguro de credenciais.

Particionar seu site

No projeto do seu site, certifique–se de que páginas seguras que exigem acesso autenticado sejam colocadas em um subdiretório separado das páginas que podem ser acessadas anonimamente. A Figura 10.3 mostra uma disposição típica da Solução Visual Studio .NET na janela do Explorer. Observe como a página de logon Formulários é colocada juntamente com outras páginas restritas em um subdiretório separado.

Subdiretório para páginas restritas que exigem acesso autenticado

Figura 10.3
Subdiretório para páginas restritas que exigem acesso autenticado

Observação: se você estiver usando o Server.Transfer no seu aplicativo para transferência de uma página anônima para uma página segura, o .NET Framework versão 1.1 ou mais recente ignora as verificações de autenticação, de modo que os códigos que usam o Server.Transfer devem ser verificados para garantir que não sejam transferidos para um diretório seguro.

Proteger páginas restritas com o SSL

Para garantir que o SSL seja usado para proteger as credenciais de logon publicadas a partir do formulário de logon e que o cookie de autenticação transmitiu solicitações subseqüentes de páginas restritas, configure as pastas seguras no IIS para exigir SSL. Isso define o atributo AccessSSL=true para a pasta na metabase do IIS. Solicitações por páginas nas pastas seguras só serão bem–sucedidas se o https for usado na URL de solicitação.

Para o SSL, é preciso ter um certificado do servidor instalado no servidor Web. Para obter mais informações, consulte "How To: Setup SSL on a Web Server" na seção "How To" de "Microsoft patterns & practices Volume I, Building Secure ASP.NET Web Applications: Authentication, Authorization, and Secure Communication" em http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/secnetlpMSDN.asp (em inglês).

Usar a autorização de URL

Para permitir acesso anônimo a páginas públicas, use o elemento <authorization> a seguir.

<system.web> 
  <!-- The virtual directory root folder contains general pages. 
       Unauthenticated users can view them and they do not need  
       to be secured with SSL.-->  
  <authorization> 
    <allow users="*" /> 
  </authorization> 
</system.web> 

Use o elemento <authorization> a seguir dentro de um elemento <location> no Web.config para negar acesso a usuários não autenticados e forçar um redirecionamento para a página de logon especificada no elemento <forms>:

<!-- The restricted folder is for authenticated and SSL access only.--> 
<location path="Secure" > 
  <system.web> 
    <authorization> 
      <deny users="?" /> 
    </authorization> 
  </system.web> 
</location>

Proteger o cookie de autenticação

Para impedir ataques de seqüestro de seção e repetição de cookie, proteja o cookie certificando–se de que ele é transmitido apenas por conexões SSL com o uso de um protocolo HTTPS. Para diminuir ainda mais os riscos, criptografe o cookie antes de enviá–lo ao cliente e limite seu período de validade. Para proteger o cookie de autenticação:

Restrinja o cookie de autenticação a conexões HTTPS.

Criptografe o cookie.

Limite o tempo de vida do cookie.

Considere o uso de um período de validade fixo.

Não torne os cookies de autenticação persistentes.

Mantenha os cookies de autenticação e de personalização separados.

Use nomes e caminhos de cookie distintos.

Restringir a transmissão de cookies de autenticação a conexões HTTPS

Os cookies suportam uma propriedade "secure" que determina se os navegadores devem ou não enviar o cookie de volta para o servidor. Com a configuração da propriedade segura, o cookie é enviado pelo navegador apenas a uma página segura solicitada com o uso de uma URL HTTPS.

Se estiver usando o .NET Framework versão 1.1, defina a propriedade segura usando o requireSSL="true" no elemento <forms>, como segue:

<forms loginUrl="Secure\Login.aspx" 
       requireSSL="true" . . . /> 

Se estiver usando o .NET Framework versão 1.0, defina a propriedade segura manualmente no manipulador de eventos Application_EndRequest no Global.asax, usando os seguintes códigos:

protected void Application_EndRequest(Object sender, EventArgs e)  
{ 
  string authCookie = FormsAuthentication.FormsCookieName; 
  foreach (string sCookie in Response.Cookies)  
  { 
    if (sCookie.Equals(authCookie)) 
    {  
      // Set the cookie to be secure. Browsers will send the cookie 
      // only to pages requested with https 
      Response.Cookies[sCookie].Secure = true; 
    } 
  } 
} 

Criptografar o cookie

Criptografe o conteúdo do cookie mesmo se estiver usando SSL. Isso impede que um invasor exiba ou modifique o cookie, se conseguir roubá–lo utilizando uma exploração XSS. Nesse caso, o invasor ainda pode usar o cookie para obter acesso ao seu aplicativo. A melhor maneira de reduzir esse risco é implementando as contramedidas apropriadas para impedir ataques XSS (anteriormente descritos neste módulo em "Cross–Site Scripting"), e limitando o tempo de vida do cookie, como descrito na próxima recomendação.

Para que o cookie tenha privacidade e integridade, defina o atributo protection no elemento <forms>, como segue:

<forms protection="All"    Privacy and integrity 

Limitar o tempo de vida do cookie

Limite o tempo de vida do cookie para reduzir a quantidade de tempo durante o qual um invasor poderá usar um cookie capturado para obter acesso por falsificação ao seu aplicativo.

<forms timeout="10"                Reduced cookie lifetime (10 minutes)

Considerar o uso de um período de validade fixo

Considere a definição de slidingExpiration="false" no elemento <forms> para estabelecer a validade do cookie, em vez de redefinir o período de validade após cada solicitação da Web. Isso é particularmente importante se você não estiver usando SSL para proteger o cookie.

Observação: esse recurso está disponível no .NET Framework versão 1.1.

Não tornar os cookies de autenticação persistentes

Não torne os cookies de autenticação persistentes, pois eles são armazenados no perfil do usuário e podem ser roubados se um invasor conseguir acesso físico ao computador do usuário. Você pode especificar um cookie não persistente ao criar o FormsAuthenticationTicket, como segue:

FormsAuthenticationTicket ticket =  
               new FormsAuthenticationTicket( 
                        1,                           // version 
                        Context.User.Identity.Name,  // user name 
                        DateTime.Now,                // issue time 
                        DateTime.Now.AddMinutes(15), // expires every 15 mins 
                        false,                       // do not persist the cookie 
                        roleStr );                   // user roles 

Manter os cookies de autenticação e de personalização separados

Mantenha os cookies de personalização que contêm preferências específicas do usuário e dados não confidenciais separados dos cookies de autenticação. Um cookie de personalização roubado pode não representar uma ameaça à segurança, contudo, o invasor pode usá–lo para acessar seu aplicativo.

Usar nomes e caminhos de cookie distintos

Use valores de atributo para nomes e caminhos exclusivos no elemento <forms>. Ao garantir nomes exclusivos, você evita os problemas que podem ocorrer ao hospedar vários aplicativos no mesmo servidor. Por exemplo, se você não usar nomes distintos, é possível que um usuário autenticado em um aplicativo faça uma solicitação a outro aplicativo sem ser redirecionado à página de logon do segundo aplicativo.

Para obter mais informações, consulte os artigos da Base de Dados da Microsoft 313116, "PRB: Forms Authentication Requests Are Not Directed to loginUrl Page" e 310415, "PRB: Mobile Forms Authentication and Different Web Applications" (ambos em inglês).

Usar URLs absolutas para navegação

Navegar entre áreas públicas e restritas do seu site (ou seja, entre páginas HTTP e HTTPS) é um problema, pois um redirecionamento sempre usa um protocolo (HTTPS ou HTTP) da página atual, e não da página alvo.

Depois que o usuário faz logon e navega pelas páginas de um diretório protegido por SSL, links relativos, como "..\publicpage.aspx", ou redirecionamentos para páginas http resultam em páginas sendo retornadas usando o protocolo https, o que gera uma sobrecarga de desempenho desnecessária. Para evitar isso, use links absolutos, como "http://servername/appname/publicpage.aspx", ao redirecionar de uma página HTTPS para HTTP.

Da mesma maneira, quando você redireciona para uma página segura (por exemplo, página de logon) a partir de uma área pública do seu site, é preciso usar um caminho HTTPS absoluto, como "https://servername/appname/secure/login.aspx", em vez de um caminho relativo, como restricted/login.aspx. Por exemplo, se a sua página da Web oferecer um botão de logon, use o código a seguir para redirecionar para uma página de logon segura.

private void btnLogon_Click( object sender, System.EventArgs e ) 
{ 
  // Form an absolute path using the server name and v-dir name 
  string serverName =  
         HttpUtility.UrlEncode(Request.ServerVariables["SERVER_NAME"]); 
  string vdirName = Request.ApplicationPath; 
  Response.Redirect("https://" + serverName + vdirName +  
                    "/Restricted/Login.aspx"); 
}

Usar um gerenciamento de credenciais seguro

A falsificação de identidade é uma das ameaças mais comuns relacionadas à autenticação para o seu aplicativo. Ela ocorre quando um invasor obtém acesso ao aplicativo parecendo que é outro usuário. Uma maneira de fazer isso é seqüestrar o cookie da sessão, contudo, se você possui um cookie de autenticação seguro, como descrito anteriormente, o risco é reduzido significativamente. Além disso, você deve ter um gerenciamento de credenciais e um armazenamento de usuários seguros para diminuir o risco apresentado por ataques de senha de força bruta, de dicionário e de inclusão de código SQL.

As recomendações a seguir ajudam a reduzir o risco:

Use hashes unidirecionais para senhas.

Use senhas de alta segurança.

Previna–se contra a inclusão de código SQL.

Usar hashes unidirecionais para senhas

Se o seu armazenamento de usuários for SQL Server, armazene compilações de senha unidirecional (valores hash) com um valor falso adicional aleatório. O valor falso adicional ameniza o risco de tentativas de violação de senha por força bruta, por exemplo, ataques de dicionário. A abordagem de compilação significa que você, na verdade, nunca armazena senhas. Em vez disso, você recupera a senha a partir do usuário e a valida, recalculando a compilação e comparando com o valor armazenado.

Usar senhas de alta segurança

Use expressões regulares para garantir que a senha dos usuários estão em conformidade com diretrizes de senha de alta segurança. A expressão regular a seguir pode ser usada para garantir que as senhas tenham entre 8 e 10 caracteres e contenham uma mistura de letras maiúsculas e minúsculas, bem como caracteres numéricos e especiais. Isso diminui ainda mais o risco do ataque de dicionário.

private bool IsStrongPassword( string password ) 
{ 
}

Prevenir–se contra a inclusão de código SQL

A autenticação de formulários está especialmente propensa a vulnerabilidades que levam a ataques de inclusão de código SQL devido à maneira como as credenciais de logon fornecidas pelo usuário são usadas para consultar o banco de dados. Para reduzir o risco:

Valide rigorosamente as credenciais fornecidas. Use expressões regulares para certificar–se de que elas não incluem caracteres SQL.

Use procedimentos armazenados parametrizados para acessar o banco de dados de armazenamento do usuário.

Use um logon para o banco de dados restrito e menos privilegiado.

Para obter mais informações sobre como evitar a inclusão de código SQL, consulte, "Criando Acesso Seguro aos Dados".

Início da páginaInício da página

Autorização

Você pode usar a autorização para controlar o acesso a diretórios, páginas da Web individuais, classes de página e métodos. Se necessário, também é possível incluir lógica de autorização no código do seu método. Ao criar uma autorização nas suas páginas da Web e nos seus controles, considere as seguintes recomendações:

Use a autorização de URL para controle de acesso a páginas e diretórios.

Use a autorização de arquivos com a autenticação do Windows.

Use exigências de alto nível em classes e métodos.

Use verificações de função explícitas para autorização apurada.

Usar a autorização de URL para controle de acesso a páginas e diretórios

Para controle de acesso no nível da página e do diretório, use a autorização URL, que é configurada pelo elemento <authorization>. Para limitar o acesso a arquivos ou diretórios específicos, coloque o elemento <authorization> dentro de um elemento <location>.

Para obter mais informações, consulte "Autorização, "Protegendo seus Aplicativos ASP.NET e Web Services".

Usar a autorização de arquivo com a autenticação do Windows

Se o ASP.NET estiver configurado para autenticação do Windows, o FileAuthorizationModule verificará todas as solicitações por tipos de arquivo ASP.NET. Isso inclui arquivos de página ASP.NET (.aspx), controles de usuário (.ascx) e qualquer outro tipo de arquivo mapeado pelo IIS para o filtro ISAPI do ASP.NET.

Para configurar o FileAuthorizationModule, defina as ACLs (Listas de Controle de Acesso) do Windows apropriadas nos arquivos ASP.NET.

Usar exigências de alto nível em classes e métodos

Exigências de permissão de alto nível permitem tomar decisões quanto à autorização com base na identidade e na participação da função do chamador. A identidade e a participação da função do chamador são mantidas pelo objeto principal associado à solicitação da Web atual (acessada pelo HttpContext.User). Use atributos de segurança declarativos para oferecer controles de acesso em classes e métodos, como segue:

// Declarative syntax 
[PrincipalPermission(SecurityAction.Demand,  
          Role=@"DomainName\WindowsGroup")] 
public void SomeRestrictedMethod() 
{ 
}

Usar verificações de função explícitas para uma autorização apurada

Verificações de segurança declarativas impedem que o usuário acesse uma classe ou chame um método específico. Se precisar de lógica adicional dentro de um método para tomar decisões quanto à autorização, use exigências de permissão imperativas de alto nível ou verificações de função explícitas usando IPrincipal.IsInRole. Essas abordagens permitem usar variáveis de tempo de execução adicionais para ajustar a decisão sobre a autorização. O exemplo a seguir mostra o uso de uma exigência de permissão imperativa de alto nível:

// Imperative syntax 
public void SomeRestrictedMethod() 
{ 
  // Only callers that are members of the specified Windows group 
  // are allowed access 
  PrincipalPermission permCheck = new PrincipalPermission( 
                                         null, @"DomainName\WindowsGroup"); 
  permCheck.Demand(); 
  // Some restricted operations (omitted) 
} 

O exemplo a seguir mostra o uso de IPrincipal.IsInRole:

public void TransferMoney( string fromAccount, 
                           string toAccount, double amount) 
{ 
  // Extract the authenticated user from the current HTTP context. 
  // The User variable is equivalent to HttpContext.Current.User if you  
  // are using an .aspx page (or .asmx) 
  WindowsPrincipal authenticatedUser = User as WindowsPrincipal; 
  if (null != authenticatedUser) 
  { 
    // Note:  To retrieve the authenticated user's username, use the  
    // following line of code 
    // string username = authenticatedUser.Identity.Name; 
    // If the amount exceeds a threshold value, manager approval is required 
    if (amount > thresholdValue) { 
      // Perform a role check 
      if (authenticatedUser.IsInRole(@"DomainName\Manager") ) 
      { 
        // OK to proceed with transfer 
      } 
      else 
      { 
         throw new Exception("Unauthorized funds transfer"); 
      } 
    } 
    else 
    { 
      . . . 
    } 
  } 
} 

Você também pode ter um método que permite chamadores de várias funções diferentes. No entanto, você pode querer chamar subseqüentemente um método diferente, o que não é possível com uma segurança declarativa.

Início da páginaInício da página

Representação

Por padrão, aplicativos ASP.NET não representam o chamador original no que se refere a projeto, implementação e escalabilidade. Por exemplo, a representação impede a regulagem de conexão da camada intermediária efetiva, o que prejudica seriamente a escalabilidade do aplicativo.

Em certos casos, você pode precisar de representação (por exemplo, se precisar de uma identidade alternativa (identidade de não–processo) para acesso a recursos). Em ambientes de hospedagem, várias identidades anônimas são geralmente usadas como uma forma de isolamento do aplicativo. Por exemplo, se o seu aplicativo usa autenticação de Formulários ou Passaporte, é possível representar a conta de usuário da Internet anônima associada ao IIS com o diretório virtual do seu aplicativo.

Você pode representar o chamador original, que pode ser uma conta de usuário da Internet anônima ou uma identidade fixa. Para representar o chamador original (a identidade autenticada IIS), use a seguinte configuração:

<identity impersonate="true" /> 

Para representar uma identidade fixa, use os atributos adicionais userName e password no elemento <identity>, contudo, certifique–se de usar o Aspnet_setreg.exe para armazenar credenciais criptografadas no registro. Para obter mais informações sobre a criptografia de credenciais em arquivos de configuração e sobre o Aspnet_setreg.exe, consulte o módulo 19, "Protegendo seus Aplicativos ASP.NET e Web Services".

Usando a representação programática

Se você não deseja representar uma conta para toda a solicitação, é possível usar a representação programática para representar uma parte da solicitação. Por exemplo, você quer usar a conta de processo ASP.NET para acessar os principais recursos do seu aplicativo e o banco de dados ramificado, mas precisa acessar um recurso alternativo, como outro banco de dados remoto ou um compartilhamento de arquivo remoto, usando uma identidade alternativa.

Para fazer isso, use o IIS para configurar a conta de usuário anônima como a identidade alternativa confiável. Em seguida, use o código a seguir para criar um identificador de representação usando uma conta anônima apenas enquanto executa seu código de acesso a recursos remotos:

HttpContext context = HttpContext.Current; 
// Get the service provider from the context 
IServiceProvider iServiceProvider = context as IServiceProvider; 
//Get a Type which represents an HttpContext 
Type httpWorkerRequestType = typeof(HttpWorkerRequest); 
// Get the HttpWorkerRequest service from the service provider 
// NOTE:  When trying to get a HttpWorkerRequest type from the HttpContext 
// unmanaged code permission is demanded. 
HttpWorkerRequest httpWorkerRequest =  
     iServiceProvider.GetService(httpWorkerRequestType) as HttpWorkerRequest; 
// Get the token passed by IIS 
IntPtr ptrUserToken = httpWorkerRequest.GetUserToken(); 
// Create a WindowsIdentity from the token 
WindowsIdentity winIdentity = new WindowsIdentity(ptrUserToken); 
// Impersonate the user 
Response.Write("Before impersonation: " +  
                WindowsIdentity.GetCurrent().Name + "<br>"); 
WindowsImpersonationContext impContext = winIdentity.Impersonate(); 
Response.Write("Impersonating: " + WindowsIdentity.GetCurrent().Name + "<br>); 
// Place resource access code here 
// Stop impersonating 
impContext.Undo(); 
Response.Write( "After Impersonating: " +  
                WindowsIdentity.GetCurrent().Name + "<br>"); 

Observação: essa abordagem assume a autenticação de Formulários ou Passaporte onde o diretório virtual do seu aplicativo é configurado no IIS para acesso anônimo a suporte.

Se você usar esse código, use a seguinte configuração <identity>:

<identity impersonate="false" />

Observação: o código exige permissão de código não gerenciado SecurityPermission(SecurityPermissionFlag.UnmanagedCode), que é concedida apenas a aplicativos da Web totalmente confiáveis.

Início da páginaInício da página

Dados confidenciais

Dados confidenciais incluem detalhes sobre a configuração do aplicativo (por exemplo, seqüências de caracteres para conexão e credenciais de conta de serviço) e dados específicos do aplicativo (por exemplo, números de cartão de crédito do cliente). As recomendações a seguir o ajudarão a reduzir o risco ao gerenciar dados confidenciais:

Não transmita dados confidenciais de página para página.

Evite senhas em texto sem formatação em arquivos de configuração.

Use DPAPI para evitar o gerenciamento de chaves.

Desative o cache de saída para dados confidenciais.

Não transmitir dados confidenciais de página para página

Evite usar qualquer opção de gerenciamento de estado do cliente, como estado de exibição, cookies, seqüência de caracteres para consulta ou variáveis de campo de formulário oculto, para armazenar dados confidenciais. Os dados podem ser adulterados e exibidos em texto não criptografado. Use as opções de gerenciamento de estado do servidor, como um banco de dados do SQL Server, para proteger a troca de dados.

Evitar senhas em texto sem formatação em arquivos de configuração

Os elementos <processModel>, <sessionState> e <identity> no Machine.config e no Web.config possuem os atributos userName e password. Não os armazene em texto sem formatação. Armazene credenciais criptografadas no registro usando a ferramenta Aspnet_setreg.exe.

Para obter mais informações sobre a criptografia de credenciais em arquivos de configuração e sobre o Aspnet_setreg.exe, consulte, "Protegendo seus Aplicativos ASP.NET e Web Services".

Usar a DPAPI para evitar o gerenciamento de chaves

A DPAPI é ideal para criptografar segredos, como seqüência de caracteres para conexão e credenciais de contas de serviço. Se as suas páginas precisam usar esse tipo de dado de configuração, use a DPAPI para impedir o problema do gerenciamento de chaves.

Para obter mais informações, consulte "Criptografia”, "Criando Conjuntos Seguros".

Desativar o cache de saída para dados confidenciais

Se a sua página contém dados confidenciais, como senha, número de cartão de crédito ou status da conta, então, ela não deve ser armazenada em cache. Para desativar o cache para uma página específica, use os seguintes atributos de nível de página:

<%@ Page OutputCache Duration="0" Location="None" VaryByParam="None" %>
Início da páginaInício da página

Gerenciamento de sessão

Há dois principais fatores que devem ser considerados para fornecer gerenciamento seguro de sessões. Em primeiro lugar, certifique–se de que o identificador da sessão não pode ser usado para acessar páginas em que são realizadas operações seguras ou para acessar itens confidenciais de dados. Em segundo, se os dados da sessão contiverem itens confidenciais, você deve proteger os dados, inclusive o armazenamento da sessão.

Eis dois tipos de identificador associados ao gerenciamento de sessão:

Token de sessão. Esse identificador é gerado automaticamente pelo ASP.NET se o estado de sessão estiver ativado, por exemplo, com a configuração do atributo mode do elemento <sessionState> para InProc, SQLServer ou StateServer.

Observação: você pode substituir a configuração <sessionState> e desativar e ativar o estado da seção por página usando o atributo EnableSessionState na marca @Page.

Identificador de autenticação. Ele é gerado por mecanismos de autenticação, como Autenticação de formulários, para registrar a sessão de um usuário autenticado. Com um identificador de autenticação válido, o usuário pode acessar partes restritas do seu site.

As recomendações a seguir ajudam a criar um gerenciamento seguro de sessão:

Exija autenticação para páginas confidenciais.

Não confie nas opções de gerenciamento de estado do cliente.

Não misture identificadores de sessão e identificadores de autenticação.

Use o SSL efetivamente.

Proteja os dados da sessão.

Exigir autenticação para páginas confidenciais

Certifique–se de autenticar os usuários antes de permitir o acesso a partes confidenciais ou restritas do seu site. Se você usa autenticação segura e protege o identificador de autenticação com SSL, então, a sessão do usuário é segura, pois o invasor não consegue seqüestrar e repetir o identificador da sessão. O invasor precisaria do identificador de autenticação para passar pela autorização.

Para obter mais informações sobre como proteger o identificador de autenticação para a Autenticação de formulários, consulte "Autenticação de formulários" neste módulo.

Não confiar nas opções de gerenciamento de estado do cliente

Evite usar qualquer opção de gerenciamento de estado do cliente, como estado de exibição, cookies, seqüência de caracteres para consulta ou campos de formulário ocultos, para armazenar dados confidenciais. As informações podem ser adulteradas e exibidas em texto não criptografado. Use as opções de gerenciamento de estado do servidor, como um banco de dados, para armazenar dados confidenciais.

Não misturar identificadores de sessão e identificadores de autenticação

O gerenciamento seguro de sessão exige que você não misture os dois tipos de identificador. Em primeiro lugar, proteja o identificador de autenticação para certificar–se de que um invasor não conseguirá capturá–lo e usá–lo para acessar áreas restritas do seu aplicativo. Em segundo, crie seu aplicativo de modo que o identificador de sessão sozinho não possa ser usado para acessar páginas ou dados confidenciais. O identificador de sessão deve ser usado somente para personalização ou para manter o estado do usuário em várias solicitações HTTP. Se não houver autenticação, não mantenha itens confidenciais sobre o estado do usuário.

Usar o SSL de maneira eficiente

Se o seu site possui áreas seguras e áreas para acesso público, você deve proteger as áreas autenticadas seguras com SSL. Quando um usuário alterna entre áreas seguras e públicas, o ASP.NET gera cookies de sessão (ou URL, se você tiver ativado o estado de sessão sem cookie) e os transmite em texto sem formatação, todavia, contanto que a propriedade de cookie Secure esteja definida, o cookie de autenticação nunca é transmitido por conexões HTTP não criptografadas.

Observação: você pode definir a propriedade Secure para um Cookie de autenticação de formulários definindo o requireSSL="true" no elemento <forms>.

Um invasor é capaz de obter um cookie de sessão transmitido por uma sessão HTTP não criptografada, mas se você tiver projetado seu site corretamente e colocado páginas e recursos restritos em um diretório separada e seguro, o invasor pode usá–lo para acessar apenas as páginas não seguras, destinadas ao acesso público. Nesse caso, não há ameaça de segurança, pois essas páginas não realizam operações confidenciais. Quando o invasor tenta repetir o identificador de sessão em uma página segura, ele é redirecionado à página de logon do aplicativo, pois não há identificador de autenticação.

Para obter mais informações sobre o uso da propriedade do cookie Secure e sobre como criar soluções seguras de Autenticação de formulários, consulte "Autenticação de formulários" neste módulo.

Proteger os dados da sessão

Se os dados da sessão no servidor contiverem itens confidenciais, os dados e o armazenamento precisam ser protegidos. O ASP.NET suporta vários modos de estado de sessão. Para obter mais informações sobre como proteger o estado de sessão ASP.NET, consulte "Estado de sessão", "Protegendo seus Aplicativos ASP.NET e Web Services".

Início da páginaInício da página

Manipulação de parâmetros

Os parâmetros, como os encontrados em campos de formulário, seqüências de caracteres para consulta, estado de exibição e cookies, podem ser manipulados por invasores cuja intenção em geral é acessar páginas restritas ou enganar o aplicativo para realizar operações não autorizadas.

Por exemplo, se um invasor descobrir que você está usando um esquema de identificador de autenticação de baixa segurança, como um número fácil de adivinhar dentro de um cookie, ele pode criar um cookie com um outro número e fazer uma solicitação como um usuário diferente (provavelmente com privilégios).

As recomendações a seguir o ajudarão a contornar as vulnerabilidades de manipulação de parâmetros:

Proteja o estado de exibição com MACs.

Use o Page.ViewStateUserKey para impedir ataques de um clique.

Mantenha os dados confidenciais no servidor.

Valide os parâmetros de entrada.

Proteger o estado de exibição com MACs

Se suas páginas da Web ou seus controles usam o estado de exibição para manter o estado em solicitações HTTP, certifique–se de que ele seja criptografado e que sua integridade seja verificada com o uso de MACs. Por padrão, o atributo enableViewStateMac no elemento <pages> no Machine.config garante que o estado de exibição seja protegido com um MAC.

<pages buffer="true" enableSessionState="true" 
       enableViewState="true" enableViewStateMac="true"  
       autoEventWireup="true" validateRequest="true"/> 

Observação: a diretiva @Page também suporta os atributos mencionados, permitindo personalizar as configurações por página.

Embora você possa optar por ativar ou desativar o estado de exibição conforme o controle, a página ou o aplicativo, certifique–se de que enableViewStateMac esteja definido como verdadeiro sempre que usar o estado de exibição.

Server.Transfer

Se o seu aplicativo usa o Server.Transfer, como mostrado abaixo, e define o segundo parâmetro Booleano opcional como verdadeiro para que as coleções QueryString e Form sejam preservadas, e ainda se o enableViewStateMac estiver definido como verdadeiro, então, o comando falhará.

Server.Transfer("page2.aspx", true); 

Se você omitir o segundo parâmetro e defini–lo como falso, haverá um erro. Se você deseja preservar as coleções QueryString e Form em vez de definir o enableViewStateMac como falso, utilize a solução discutida no Artigo da Base de Dados da Microsoft 316920, "PRB: "View State Is Invalid" Error Message When You Use Server.Transfer" (em inglês).

Para obter mais informações sobre a configuração do elemento <machineKey> para criptografia do estado de exibição e verificações de integridade, consulte, "Protegendo seus Aplicativos ASP.NET e Web Services".

Usar o Page.ViewStateUserKey para impedir ataques de um clique

Se você autentica seus chamadores e usa o estado de exibição, defina a propriedade Page.ViewStateUserKey no manipulador de eventos Page_Init para impedir ataques de um clique. O ataque de um clique ocorre quando um invasor cria uma página da Web pré–preenchida (.htm ou .aspx) com estado de exibição. O estado de exibição pode ser gerado a partir de uma página criada pelo invasor, por exemplo, uma página de compras com 100 itens. O invasor atrai o usuário distraído para navegar em sua página, em seguida, envia a página ao servidor em que o estado de exibição é válido. O servidor não tem como saber que o estado de exibição é proveniente de um invasor. A validação de estado de exibição e de MACs não impede o ataque, pois o estado de exibição é válido e a página é executada no contexto de segurança do usuário.

Defina a propriedade Page.ViewStateUserKey para um valor exclusivo adequado como uma contramedida para o ataque de um clique. O valor deve ser único para cada usuário e é, tipicamente, um nome de usuário ou um identificador. Quando o invasor cria o estado de exibição, a propriedade ViewStateUserKey é inicializada com seu nome. Quando o usuário envia a página para o servidor, ela é inicializada com o nome do invasor. Como resultado, a verificação do MAC do estado de exibição falha e é gerada uma condição de exceção.

Observação: geralmente, esse ataque não é um problema para páginas navegadas anonimamente (nas quais não há nome de usuário disponível), pois esse tipo de página não realiza transações confidenciais.

Manter os dados confidenciais no servidor

Não confie em parâmetros de entrada, especialmente quando eles são usados para tomar decisões de segurança no servidor. Além disso, não use parâmetros em texto não criptografado para nenhuma forma de dados confidenciais. Em vez disso, armazene os dados confidenciais no servidor em um armazenamento de sessão e use um identificador de sessão para fazer referência aos itens no armazenamento. Certifique–se de que o usuário é autenticado com segurança e de que o identificador de autenticação está adequadamente protegido. Para obter mais informações, consulte "Gerenciamento de sessão" neste módulo.

Validar os parâmetros de entrada

Valide todos os parâmetros de entrada provenientes de campos de formulário, seqüência de caracteres para consulta, cookies e cabeçalhos HTTP. A classe System.Text.RegularExpressions.Regex ajuda a validar os parâmetros de entrada. Por exemplo, o código a seguir mostra como usar essa classe para validar um nome transmitido por meio de um parâmetro de seqüência de caracteres para consulta. A mesma técnica pode ser usada para validar outras formas de parâmetro de entrada, como cookies ou campos de formulário. Por exemplo, para validar um parâmetro de cookie, use Request.Cookies em vez de Request.QueryString.

using System.Text.RegularExpressions; 
. . . 
private void Page_Load(object sender, System.EventArgs e) 
{ 
  // Name must contain between 1 and 40 alphanumeric characters 
  // together with (optionally) special characters '`´ for names such 
  // as D'Angelo 
  if (!Regex.IsMatch(Request.QueryString["name"],  
                     @"^[\p{L}\p{Zs}\p{Lu}\p{Ll}]{1,40}$")) 
    throw new Exception("Invalid name parameter"); 
  // Use individual regular expressions to validate all other 
  // query string parameters 
  . . . 
} 

Para obter mais informações sobre o uso de expressões regulares e sobre como validar dados de entrada, consulte "Validação de entradas" neste módulo.

Início da páginaInício da página

Gerenciamento de exceções

A manipulação correta de exceções nas suas páginas da Web impede que detalhes confidenciais sobre exceções sejam revelados ao usuário. As recomendações a seguir aplicam–se a páginas da Web ASP.NET e controles

Retorne páginas de erro genéricas ao cliente.

Implemente manipuladores de erro no nível da página ou do aplicativo.

Para obter mais informações sobre o gerenciamento de exceções, consulte, "Criando Conjuntos Seguros".

Retornar páginas de erro genéricas ao cliente

Retorne uma página de erro genérica para o usuário no caso de uma exceção não tratada, ou seja, uma que se propaga além dos limites do aplicativo. Para isso, configure o elemento <customErrors> como segue:

<customErrors mode="On" defaultRedirect="YourErrorPage.htm" /> 

A página de erro deve incluir uma mensagem de erro genérica adequada, possivelmente com detalhes de suporte adicionais. O nome da página que gerou o erro é transmitida à página de erro por meio de parâmetro de consulta aspxerrorpath.

Você também pode usar várias páginas de erro para diferentes tipos de erro. Por exemplo:

<customErrors mode="On" defaultRedirect="YourErrorPage.htm"> 
   <error statusCode="404" redirect="YourNotFoundPage.htm"/>               
   <error statusCode="500" redirect="YourInternalErrorPage.htm"/>               
</customErrors> 

Para páginas individuais, é possível fornecer uma página de erro usando o seguinte atributo no nível da página:

<% @ Page ErrorPage="YourErrorPage" %>

Implementar manipuladores de erro na página ou no aplicativo

Se você precisa capturar e processar exceções não tratadas na página, crie um manipulador para o evento Page_Error semelhante ao mostrado abaixo.

public void Page_Error(object sender,EventArgs e) 
{ 
  // Get the source exception details 
  Exception ex = Server.GetLastError(); 
  // Write the details to the event log for diagnostics 
  . . . 
  // Prevent the exception from propagating and generating an  
  // application level event (Application.Error) 
  Server.ClearError(); 
}   

Se for permitida a propagação das exceções a partir do manipulador da página ou se não houver um manipulador, será gerado um evento de erro de aplicativo. Para capturar eventos no nível do aplicativo, implemente Application_Error no Global.asax, como segue:

protected void Application_Error(Object sender, EventArgs e)  
{ 
  //  Write to the event log. 
}
Início da páginaInício da página

Auditoria e log

A identidade de processo ASP.NET padrão para aplicativos da Web pode gravar novos registros no log de eventos, mas não possui permissões suficientes para criar novas fontes de evento. Para resolver esse problema, existem duas opções. Você pode criar uma classe de instalador, carregada na instalação quando os privilégios do administrador estão disponíveis, ou configurar as permissões na chave de registro EventLog para permitir que a identidade de processo ASP.NET (ou uma identidade representada) crie fontes de evento no tempo de execução. Recomendamos a primeira abordagem.

Para criar uma fonte de evento de aplicativo no momento da instalação

1.

Clique com o botão direito no seu projeto na janela do Solution Explorer no Visual Studio .NET, aponte para Add e clique em Add Component.

2.

Selecione Installer Class na lista de modelos e forneça um nome de arquivo de classe adequado.

Essa ação cria uma nova classe de instalador, explicada com o atributo RunInstaller(true).

RunInstaller(true) 
public class EventSourceInstaller : System.Configuration.Install.Installer 
{ 
 . . . 
} 

3.

Exiba a nova classe de instalador em Design view, exiba a Toolbox e clique em Components na Toolbox. Arraste um componente EventLogInstaller para a superfície de trabalho do Designer.

Observação: se o EventLogInstaller não aparecer na Toolbox, clique nela com o botão direito e, em seguida, clique em Add/Remove Items. Depois, selecione EventLogInstaller para adicionar esse tipo de componente.

4.

Defina as propriedades de EventLogInstaller a seguir:

Log. Defina essa propriedade para "Application", que é o nome do log de eventos que você deve usar. Você pode usar o log padrão do aplicativo ou criar um log específico para ele.

Source. Defina essa propriedade para o nome da fonte do evento, que é geralmente o nome do seu aplicativo.

5.

Crie seu projeto e, em seguida, crie uma instância da classe do instalador no momento da instalação.

As instâncias da classe do instalador são criadas automaticamente e carregadas se você usar um projeto de Configuração e Implantação .NET para criar um arquivo de instalação do Windows (.msi). Se você utiliza o xcopy ou uma implantação equivalente, use o utilitário InstallUtil.exe para criar uma instância da classe do instalador e executá–la.

6.

Para confirmar a geração bem–sucedida da fonte de eventos, use um editor de registro e vá para:

HKLM\System\CurrentControlSet\Services\EventLog\Application\{source name} 

Confirme se a chave existe e se contém um valor de seqüência de caracteres EventMessageFile que aponta para o arquivo padrão de mensagem de evento do .NET Framework:

\Windows\Microsoft.NET\Framework\{version}\EventLogMessages.dll

Se você já tiver um aplicativo e não deseja criar uma classe de instalador, será preciso conceder à identidade de processo ASP.NET os direitos de acesso corretos na chave de registro do log de eventos. Para detalhes sobre a chave de registro e os direitos de acesso precisos que serão necessários, consulte "Log de eventos", "Protegendo seus Aplicativos ASP.NET e Web Services".

EventLogPermission

Conforme a diretiva de segurança de acesso a códigos, a EventLogPermission deve ser concedida ao código que grava no log de eventos. Isso se torna um problema se o seu aplicativo da Web está configurado para ser executado como parcialmente confiável. Para informações sobre como gravar no log de eventos a partir de um aplicativo da Web parcialmente confiável, , "Usando a Segurança do Acesso ao Código com o ASP.NET".

Início da páginaInício da página

Resumo

Este módulo começou mostrando as principais ameaças contra as quais você precisa se prevenir ao criar páginas da Web e controles. Vários ataques no nível do aplicativo dependem de vulnerabilidades na validação de entradas. Tome um cuidado especial nessa área para certificar–se de que sua estratégia de validação é eficiente e que todos os dados processados a partir de uma fonte não confiável sejam adequadamente validados. Outra vulnerabilidade comum é a falha em proteger cookies de autenticação. A seção "Autenticação de formulários" deste módulo ofereceu contramedidas efetivas a serem aplicadas para impedir o acesso não autorizado, o seqüestro de sessões e os ataques de repetição de cookie.

Início da páginaInício da página

Recursos adicionais

Para obter mais informações, consulte os recursos a seguir:

Para obter mais informações sobre como estabelecer uma configuração segura do Machine.config e do Web.config, consulte o módulo 19, "Protegendo seus Aplicativos ASP.NET e Web Services".

Para uma lista de verificação imprimível, consulte "Lista de verificação: protegendo o ASP.NET" na seção "Listas de verificação" deste guia.

Para informações sobre a proteção da estação de trabalho do seu desenvolvedor, consulte "Como: proteger sua estação de trabalho do desenvolvedor" na seção "Como" deste guia.

Para obter mais informações sobre autenticação e autorização no ASP.NET, consulte o módulo 8, "ASP.NET Security" em "Microsoft patterns & practices Volume I, Building Secure ASP.NET Web Applications: Authentication, Authorization, and Secure Communication" em http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetch08.asp (em inglês).

Para instruções passo a passo sobre o uso de Autenticação de formulários, consulte "How To: Use Forms Authentication with SQL Server 2000" e "How To: Use Forms Authentication with Active Directory" na seção "How To" de "Microsoft patterns & practices Volume I, Building Secure ASP.NET Web Applications: Authentication, Authorization, and Secure Communication" em http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetHT00.asp (em inglês).

Para obter mais informações sobre o uso de expressões regulares, consulte o Artigo da Base de Dados da Microsoft 308252, "HOW TO: Match a Pattern by Using Regular Expressions and Visual C# .NET" (artigo em inglês).

Para obter mais informações sobre a validação de entradas de usuário no ASP.NET, consulte o artigo MSDN "User Input Validation in ASP.NET" em http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/pdc_userinput.asp (em inglês).

Para obter mais informações sobre a propriedade de cookie Secure, consulte a RFC2109 no site W3C em http://www.w3.org/Protocols/rfc2109/rfc2109 (em inglês).

Para obter mais informações sobre as considerações de segurança da competição Open Hack, leia o artigo MSDN "Building and Configuring More Secure Web Sites" em http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/openhack.asp (em inglês).


Início da páginaInício da página