sábado, 27 de agosto de 2011

Falhas de Segurança de Programação

Enquanto todas as atenções se voltam para os problemas de segurança de rede e as invasões de hackers com cada vez maiores conhecimentos técnicos e cada vez mais audaciosos outro problema de abrangência e gravidade muito maior é deixado de lado : A segurança contra falhas de programação que sejam capazes de expor um sistema na web.
Testei muitos sites e me assustei com o que encontrei : Sites de e-commerce muito famosos encontram-se com falhas de programação grosseiras que permitem que qualquer um roube informações de seus bancos de dados. Ironicamente estes mesmos sites utilizam o selo da verisign "site seguro". Com os testes me assustei com a constatação de que não existe e-commerce seguro. E não estou falando da possibilidade de super-hackers quebrarem qualquer coisa, estou falando que qualquer amador tem em mãos todos os recursos necessários para entrar em sites de e-commerce famosos : um browser e o notepad.
Vale ainda mencionar que plataforma utilizada não fez a menor diferença : testei sites com ASP, PHP, ColdFusion, SQL Server, Oracle, Access, MySQL, todos com o bug, que é um bug de programação e independe da linguagem utilizada.
O que ? Falha de programação não faz isso ? Pois veja e se assuste.

Tudo começa na caixa de login e senha. É necessário que a aplicação pegue o login e senha digitados e pesquise-os no banco. A regra basica para evitar falhas de segurança é : JAMAIS faça uma pesquisa no banco com algo que o usuário informou sem trocar primeiramente os caracteres reservados.
Mas o fato é que ninguém está seguindo esta regra. E o resultado são três algorítimos falhos :
A) Vai-se ao banco pesquisando pelo nome e senha. Se houver registro de retorno o nome e senha é válido e o usuário está logado.
O mais falho de todos. É muito fácil ultrapassar este algorítimo.
B) Vai-se ao banco pesquisando nome e senha. Se houver registro de retorno e a senha for igual a senha digitada o login é válido e o usuário entra.
Um pouco mais seguro, mas ainda sim no ambiente Web a invasão deste site é simples, sem grandes mistérios.
C) Vai-se ao banco pesquisando o nome. Se houver registro de retorno e a senha for igual a senha digitada o login é válido e o usuário entra.
Tão falho quanto o B

Existe a lenda de que evitando-se o algorítimo A o site estará seguro. Pura lenda. Se a regra básica, JAMAIS FAZER PESQUISA NO BANCO COM INFORMAÇÃO DO USUÁRIO SEM ANTES TRATAR CARACTERES RESERVADOS, não for atendida então seu site é um grande convite a hackers.
Passo 1 : Obtendo informações sobre a vítima.
Tudo se inicia na caixa de login. Inicia-se digitando-se um apóstrofo e clicando-se no botão para seguir adiante. As reações podem ser as mais diversas :
Uma mensagem de erro gerada pelo próprio site :
Essa é a melhor reação possível, quando bem utilizada, quando não fica inútil. O fato da própria aplicação no site gerar a mensagem de erro significa que, se é que houve um erro ocorreu um tratamento e o pretenso hacker ficará sem saber o que ocorreu em consequencia da entrada dele na caixa de login.
Mas a alegria do administrador do site pode durar pouco : Alguns sites tem o costume de dar mensagens diferenciadas de acordo com o erro, tal como "usuario inválido", "senha inválida" ou "erro desconhecido". Neste caso o procedimento de tratar o erro é inútil, pois a mensagem de erro personalizada de acordo com o erro está informando ao hacker que a tentativa dele gerou algum resultado.
O ideal é dar uma mensagem padrão do tipo "Login inválido" para qualquer erro que porventura ocorra durante o processo de login, desta forma o hacker, a princípio, não saberá se as tentativas dele geraram algum resultado ou não, dificultando (não impedindo) a ação do pretenso hacker.
Vale mencionar que o tratamento padrão dos apóstrofos faz com que o apóstrofo digitado na caixa de login seja visto como um usuário. Assim sendo se o site está usando mensagens diferenciadas e, como resposta ao apóstrofo, o pretenso hacker recebe alguma mensagem diferente de "usuário inválido", ele está na verdade recebendo um convite do tipo "continue, você está no caminho certo e vai conseguir".
Mensagem do servidor : Caracteres inválidos no login :
Pode ser vista como a solução do problema. Se disparada a partir do servidor significa que o algorítimo de login testou o login e identificou que haviam caracteres inválidos, não indo ao banco. Isso fará com que o hacker de imediato desista do seu site. Desista, mas espalhe a todos que seu site é mal programado, já que esta não é a forma correta de se tratar os apóstrofos, apesar de funcionar.
Esteja atento para o fato de que a mensagem deve partir do servidor, não do client. Infelizmente muitos programadores WEB tem dificuldades em diferenciar isso, mas esteja certo que um hacker o faz de olhos fechados e mãos nas costas.

Mensagem do Client : Caracteres inválidos no login :
Nesta hora o hacker dá um risinho e arregaça as mangas : isso é um desafio, ele foi desafiado por um mal programador ! Que audácia !
Em menos de 5 minutos o hacker edita o código fonte, elimina a validação e invade o site. Manter validação apenas no client é o mesmo que não manter validação nenhuma.
Claro que esta mensagem ainda não é uma certeza de sucesso : Se a validação estiver duplicada tanto no client como no servidor o hacker vai perder tempo a toa. Para a sorte dele, porém, são poucos os desenvolvedores que tem verdadeiro conhecimento da arquitetura WEB para desenvolver desta forma.
Erro 500.100
Característico do Windows 2000, esse erro impede que o hacker veja detalhes sobre o erro ocorrido no código ASP, dificultando a ação do hacker. Ponto para o site.
Mas em primeiro lugar deve-se destacar que isso foi conseguido apenas por acaso, já que é a configuração default do windows 2000. Isso demonstra total desconhecimento por parte do desenvolvedor do fato de existir nos servidores Web uma configuração que faz com que em caso de erro apenas uma mensagem de erro padrão seja exibida. Ponto para o hacker, já que se o desenvolvedor desconhece isso as chances de haverem outras falhas são grandes.
Além disso o erro 500.100 é tipico do windows 2000. Assim sendo o hacker já sabe o que está rodando do outro lado e saber isso é o primeiro passo para um ataque via rede, já que basta uma pequena busca no astalavista para descobrir os pontos falhos do sistema. Nosso artigo porém não irá se aprofundar nisso.
Ocorreu uma falha, contacte o administrador
Parecido com o erro 500.100, esta é a mensagem padrão normalmente utilizada quando o administrador do servidor configura uma mensagem em resposta a erros ocorridos no servidor (comentei isso logo acima).
Esta mensagem é um pouquinho melhor que o erro 500.100 pois com esta mensagem o hacker não ganha informação alguma sobre o sistema que está rodando do outro lado. Porém ele ganha algo importante : A informação de que ocorreu um erro. Isso já é o suficiente para que ele saiba que está no caminho certo. O melhor teria sido tratar o erro em código e dar uma mensagem a partir do código de programação, como mencionado no primeiro tópico.
Mensagem de erro de acesso a banco :
Tudo o que o hacker mais deseja é ver esta mensagem. Ela diz tudo :
- O banco que está rodando
- A forma de acesso a banco : ODBC/OLEDB
- O sistema operacional que está rodando
(muitas vezes identificado por dedução)
- Detalhes sobre o porque do erro
Estas informações ajudam o hacker a invadir os servidores de rede, já que identificou o que está do outro lado e pode buscar informações sobre as falhas de segurança existentes. Porém este não é o assunto de nosso artigo.
Para invadir através do próprio site, veja a utilidade das informações para o hacker :
Identificação do banco : Access não permite múltiplas instruções enviadas em conjunto, então o hacker já sabe o que não tentar. SQL Server permite. Oracle permite, mas separadas por ";". Além disso, de acordo com o banco o invasor pode utilizar instruções específicas de cada banco para manipular os dados ou obter informações.
Detalhes sobre o porque do erro : Em nosso exemplo estes "detalhes" normalmente contém a instrução SQL que causou o problema, o que diz tudo que o hacker precisa : como alterar a instrução para poder entrar. Quando não contém a instrução contém a mensagem de erro pela qual o hacker pode deduzir como é a instrução.
Além disso a mensagem de erro informa em que arquivo ocorreu o erro. No ASP isso pode ser um problema pois alguns programadores tem o vício de fazer include de arquivos com extensão .INC. De posse do nome do arquivo o hacker roubará o código fonte contido no arquivo .INC sem dificuldades, passando a saber detalhes sobre como é feita a conexão com o banco, as regras de negócio implementadas no servidor e até mesmo detalhes do algorítimo que podem lhe mostrar como invadir o site. Falarei do assunto mais adiante neste artigo.

Passo 2 : Iniciando o processo de invasão
Se o hacker recebeu uma mensagem popup (típica do client) informando sobre caracteres inválidos a forma de invasão se altera e ele não passa pelo passo 2, não agora pois não funcionaria. Explicaremos isso mais adiante.
Em todos os outros casos o hacker segue adiante com a invasão digitando : ' or '1'='1 tanto na caixa de login como na caixa de senha.
A digitação disso, porém, pode ter suas dificuldades : o hacker pode esbarrar um um maxlength (para leigos: tamanho máximo) configurado ou na caixa de login ou na de senha. Na caixa de login, além de ser incomum, ele logo verá. Na caixa de senha, devido a senha ser trocada por *, fica difícil identificar e o hacker deverá estar bem atento para perceber o problema. Identificando o problema do maxlength, é fácil resolver : Basta tira-lo, assim como seria tirada a validação no client. Então há aqui um pequeno desvio antes de continuar, falaremos sobre isso posteriormente.
Caso tudo de certo, as chances de haver entrado são grandes. Como ? Não entendeu ? Veja a montagem da instrução sql abaixo :
sql="select * from usuarios where login='" & vlogin & "' and senha='" & vsenha & "'"
Essa seria a montagem de uma busca pelo usuário no banco em ASP. Outras linguagens, apesar de terem síntaxes para a montagem diferente, geram a mesma instrução SQL e por isso ficam sujeitas ao mesmo bug de programação.
Que bug ? Não entendeu ? Então para ficar mais claro veja a instrução SQL pura concatenada com o que o hacker digitou :

select * from usuarios where login='' or '1'='1' and senha='' or '1'='1'

Sacou ? Foi usada a caixa de login para alterar o significado da instrução SQL e uma instrução que normalmente traria registros apenas se o login e senha estivessem corretos agora trás como resposta todos os usuários do banco. Lembre-se que '1' sempre será igual a '1', retornando true para todos os registros, trazendo todos como resultado.
A próxima pergunta seria : E como os algorítimos de autenticação reagem a isso ?
Veja você mesmo :
Algorítimo A) O hacker está logado. Esse algorítimo apenas verifica se houve retorno de registros, e houve. Então pega os dados do 1o registro retornado e faz o logon (em geral isso é a colocação de informações em ambiente de sessão) utilizando estes dados. Assim o hacker já está logando com um nome de usuário e senha aleatório e tem permissão de fazer tudo em nome do usuário em questão : Obter seus dados, altera-los, fazer compras, etc.
Algorítimo B) A checagem de senha feita após o login protege este algoritimo desta entrada básica. O hacker recebe a mensagem "senha inválida" e tem que fazer uma pequena mudança de tática para entrar. Aqui vale mais um alerta : Se a recomendação que fiz lá no alto de não utilizar mensagens diferenciadas, de fornecer sempre a mesma mensagem padrão, houver sido seguida a risca, o hacker demorará a perceber o que está ocorrendo ou até mesmo não perceberá, assim a invasão será mais difícil.
Algorítimo C) Idem B
Assim sendo se o algorítimo utilizado fosse o A o hacker já estaria com acesso ao site. Seria necessário refinar um pouco o acesso, já que o registro trazido é escolhido aleatoriamente e se o programador estiver com sorte pode ser um registro de testes criado pelo próprio programador. Vamos fazer isso no passo 3, por enquanto vamos nos dedicar a como prosseguir a partir dos passos B e C.
Bem, os algorítimos B e C são mais seguros que o A, isso é inegável. Algumas informações que poderiam ser facilmente obtidas através do algorítimo A ficam inacessíveis devido ao uso do algorítimo B e C, pois já que o algorítimo faz a checagem da senha o hacker precisa saber a senha. Fica mais difícil obter-se alguns dados, mas não impossível.
Então para passar pelo algorítimo B e C o hacker precisa conhecer a senha. Isso é fácil : "senha", "password", "teste","123","1234","12345" e qualquer coisa ligada ao site (em um site de Vb encontrei "VB","visual","basic"). O truque está no fato de que o hacker não precisa conhecer o nome de login. Veja o que ele deverá digitar na caixa de login :
' or senha='teste
Na caixa de senha deve ser digitada a própria senha. Veja como fica a instrução SQL :
select * from usuarios where login='' or senha='teste' and senha='teste'
A instrução SQL pode variar um pouco, de acordo com a senha estar ou não sendo procurada no banco (algorítimo B ou C), mas o resultado acaba sendo o mesmo.
Os mais atentos observaram três coisas :
A) Apenas registros com senhas fáceis ou que o hacker seja capaz de adivinhar estarão vulneráveis.
A primeira vista sim. E isso não basta ? Em todos os sites que fiz o teste sempre havia alguém com uma dessas senhas.
De qualquer forma isso é só a primeira vista. O hacker pode construir uma aplicação que seja capaz de realizar um ataque dicionário ao site e/ou teste milhares de combinações possíveis, obtendo grande parte dos dados contidos no banco de dados do site. Voltarei a falar disso posteriormente.
B) Não se pode buscar informações de uma pessoa específica, seria necessário conhecer a senha da pessoa.
Isso é verdade, isso torna os algorítimos B e C um pouco mais seguros que o algorítimo A. Se a senha da pessoa fosse conhecida é bem provável que o hacker não precisasse ter esse trabalho todo, a não ser em uma estranha situação em que o hacker soubesse a senha mas não o login. Improvável.
C) É necessário saber o nome do campo que contém a senha.
Isso é um problema. Veja os caminhos que poderiam ser seguidos :
Adivinhar utilizando os nomes mais comuns : Na maioria dos sites que testei isso funcionou.
Estar atento a localização do site : Em um site que testei, apesar da página ser em português o banco estava em espanhol, a empresa era multinacional
Causar um erro e aproveitar-se da mensagem exibida : Mais uma terrível consequencia da má configuração do servidor - no site com banco em espanhol, que mencionei acima, só consegui passar porque a mensagem de erro me disse o nome do campo que continha a senha.
Vocês devem estar pensando : "Então se utilizar um nome absurdo para meu campo de senha e configurar o servidor corretamente vou estar seguro..." De fato, mas não usaria este método. O hacker pode simplesmente tomar um atalho e apagar todo seu banco (falarei disso depois). O fato é : Você não deveria ter deixado que ele chegasse até aqui.
Eu recomendo o seguinte : utilize as boas práticas de desenvolvimento, que mandam que você padronize nomes de variáveis. Aplique-as para nomes de campo. Por exemplo, se seu campo se chamar s_senha, ou quem sabe v_senha, ao invés de simplesmente senha, será bem mais difícil para o hacker adivinhar o nome deste campo. Já vi uma empresa utilizando cod_senha como padrão. Pois crie o seu padrão. Se por azar algum hacker chegar a este ponto dentro do seu site não conseguirá adivinhar o nome de seu campo e não poderá seguir adiante. Por outro lado o nome de campo padronizado não só não prejudicará você como também gerará ganhos em termos de qualidade de desenvolvimento.
Passo 3 : Melhorando a obtenção de dados
Agora que fizemos a invasão é hora de refinarmos seu resultado. Por exemplo : Como podemos pesquisar por um login específico ? Vamos ver exemplos em relação ao algorítimo A. Alguns exemplos podem ser adaptados para o B e C, outros não.
Digamos que desejamos procurar por uma pessoa específica. Podemos fazer algo como :
' or email like 'fulano%
Tanto na caixa de login como de senha. Teremos como resposta o registro do fulano e o algorítimo A nos deixará passar. Muitas outras combinações podem ser feitas com endereço, nome, telefone, etc., mas é necessário saber o nome dos campos.
Mas e se não for possível saber os nomes dos campos ?
Temos então o truque do comentário e do order by. Tanto o SQL Server como o Oracle aceitam o símbolo -- como comentário inline, assim tudo que estiver depois deste símbolo é ignorado. Perigoso, não ? Veja o que dá para fazer :
' or '1'='1' order by 1 --
O order by aceita uma indicação numérica ao invés do nome do campo, assim sendo ele ordenará pelo campo 1, campo 2, campo 3,etc. e o hacker terá acesso a tantos registros quantos forem os campos da tabela, tudo sem saber o nome de campo algum.
Porém se o hacker souber pelo menos o nome de 1 campo e conseguir acertar o nome da tabela (que, pelo que testei, em 80% dos casos é "usuarios"), veja o que ele poderá fazer :
' or '1'='1' and login not in (select top 1 login from usuarios) --

Obs: Instrução para SQL Server ou Access, não testei com Oracle, mas creio que funcione
Sacou ? Com esta linha ele está pegando o 2o registro da tabela. Agora basta aumentar o número do TOP (2,3,4,5,6) e ele pegará, registro por registro, a tabela inteira. Basta ter paciência.
Paciência ? Não, não precisa. É hora de irmos ao passo 4 : A automatização da invasão.
Passo 4 : A automatização da invasão
Depois de acertar o padrão da instrução SQL que permitirá que pegue todos os dados do banco é hora de automatizar.
O hacker pode criar uma aplicação VB que faça a obtenção de dados automaticamente. O componente INET do Vb pode fazer um POST para um endereço Web e obter a resposta. Veja como ele faria :
· Olhando o fonte da tela de login ele precisará identificar no Action do Form qual a página que faz o processamento do login.
· Tendo identificado isso ele deverá fazer um loop na aplicação para fazer N posts em sequencia para o endereço que ele identificou. No exemplo que fizemos acima ele terá que a cada laço incrementar o número do TOP. Nos exemplos que fizemos anteriormente ele pode montar um algorítimo que teste combinações de senhas para fazer a busca por informações no site.
· O POST para a tela de login gera um resultado, o mesmo resultado que é gerado quando ele se loga no site. Ele precisará descobrir um padrão, algum texto ou frase neste resultado que diga se ele está ou não logado. Fazendo este teste dentro do laço ele saberá se o POST funcionou ou não.
· O hacker deverá identificar a página de alteração de cadastro para poder chama-la. Deverá identificar o caminho direto para a página.
· Pelo INET ele deverá chamar a página de alteração de cadastro. Como resposta obterá a página com os dados do usuário, exatamente como ela aparece no site. Usando processamento de strings ele deverá extrair os dados do usuário e guardar em seu banco de dados
· Repetir tudo até obter tudo que ele deseja.
Assustador, não ? Não tanto quanto o último passo...
Passo 5 : Destruir tudo
A questão é : O hacker pode destruir tudo ?
' drop table usuarios --
Isso responde ? SQL Server processa isso sem problemas, Oracle precisa de um ; :
' ; drop table usuarios --

Mas tudo gera o mesmo resultado : Adeus tabela de usuários. A questão é : Existe permissão para isso ?
Tudo depende do usuário que está sendo utilizado pelo site para se conectar ao servidor Web. Se for um usuário com permissão de system administrator, db_owner ou ddl_admin (sql server) ou o equivalente no Oracle então o site estará em sérios apuros. E se não for ?
' delete usuarios
ou
' ; delete usuarios
É... sem salvação... Talvez uma pequena luz no fim do túnel : É provavel que a tabela usuários seja referenciada por diversas outras através de foreign keys. Isso fará com que o delete em questão não funcione. A salvação do site então acaba sendo um pequeno acaso. Mas a luz pode virar um trem se o DBA tiver feito deleção em cascata... que perigo !
Porém não é simples para o hacker fazer isso : Como a instrução que está sendo dada é a 2a de um SELECT o hacker não recebe nenhuma resposta visível que diga se a instrução funcionou ou não. A única excessão é quando a instrução gera um erro de compilação, então o hacker vê a mensagem de erro.
Explico. Os bancos, antes de processarem as instruções, realizam um processo de compilação na mesma. Se nesse processo houver algum erro, em geral erro de síntaxe, o hacker vê a mensagem (conforme a configuração do servidor, claro, da qual já falamos). Mas se as instruções passarem pelo processo de compilação então o hacker não verá nenhuma mensagem de erro relativa a 2a instrução. Por exemplo, ele não saberá se acertou o nome da tabela ou não. A única forma de saber se acertou ou não o nome da tabela é verificando se alguma coisa no site parou por falta da tabela.
Já que o usuário do site precisa ter permissões adequadas para fazer isso o hacker precisará identificar se tais permissões existem ou não. No SQL Server uma forma de fazer isso é a seguinte :
' raiserror('um erro',15,1) with log --
Essa instrução precisa que o usuário seja um system administrator para ser executada. Se não for, dará um erro de compilação. Assim sendo, se o hacker ver um erro como resultado saberá que o usuário não é system administrator (o que não significa que não tenha permissão de deletar tabelas), mas se nenhum erro aparecer, o hacker poderá fazer a festa.
Solução
A solução para este problema é criar usuários com permissões diferenciadas, sendo que cada área do site deve utilizar o usuário com o mínimo de permissões que aquela área precise.
Quem conhece SQL Server deve estar se perguntando : E como fazer no caso da segurança integrada, que é a melhor forma de segurança do SQL Server ?
Em primeiro lugar, garanta que o usuário não tenha permissões de DDL e mantenha as permissões de Delete e Update ao mínimo. Porém se realmente estiver disposto a sacrificar-se um pouco (código e performance) para manter a segurança faça uso das application Roles : O usuário em si não terá permissão alguma no banco, cada área do site ativa a sua própria application role com as permissões mínimas que aquela área precisa, chegando assim ao mesmo resultado que mencionei - ter um usuário distinto para cada área do site - o efeito é o mesmo.
Voltando um pouco : A eliminação das validações no client
Um pouco antes neste artigo mencionei que a validação no client funciona como um desafio ao hacker. São basicamente 2 tipos de validação que atrapalham o trabalho do hacker : A validação em JavaScript e o MaxLength.
O hacker, a principio, não tem como fazer a alteração do arquivo no servidor. Invasões do servidor via rede que possibilitariam isso não são o foco de nosso artigo. Mas para fugir das validações no client ele nem precisa fazer isso.
A característica básica das validações no client é, óbvio, serem no client. Isso significa que estão rodando na máquina do usuário, o hacker, e não no servidor. O hacker tem domínio sobre o que roda na máquina dele e é isso que faz da validação no client uma validação fraquissima, que nem deveria ser chamada de validação.
A primeira coisa que precisa ser feita neste caso é salvar a página na máquina local. Nisso o IE dá um show : basta dar o save e ele organiza tudo. Ele salva o arquivo HTM principal e cria uma sub-pasta com todos os arquivos que a página utiliza, tal como imagens, arquivos .HTM de cada divisão de um frame, etc.
Estando tudo salvo o hacker precisa abrir o arquivo .HTM principal no notepad. Se o site utiliza frames não será o arquivo principal, mas uma das partes do frame, ele precisará identificar qual. Não é tarefa muito difícil.
Tendo aberto o arquivo, o primeiro passo é fazer com que funcione offline. O formulário de login possui um parâmetro ACTION que normalmente contém um caminho relativo para uma página do site ou, as vezes, nem foi configurado (quando a página realiza POST para ela mesma). O hacker precisa ajustar este parâmetro para que a página que está em sua máquina faça um POST para a página que irá processar o login no servidor. Basta juntar o nome da página existente no Action com o domínio do site e tudo funcionará. Deve-se ter o cuidado de, não havendo action, descobrir o nome da página em questão (que é o nome da página de login) para utiliza-la.
Feito isso basta tirar a validação. Veja :
MaxLength : Não tem coisa mais fácil. Basta dar um search por maxlength e apagar.
JavaScript : Esse varia, o hacker precisará escolher a técnica que achar mais conveniente. Ele pode alterar o formulário para que o formulário não chame as funções de validação (tirando o onsubmit no form e eventuais onclick em botão) ou então apagar as validações de dentro da função em javascript, mantendo apenas seu término (que pode ser o retorno de um valor true ou um submit, isso terá que ser identificado caso a caso).
Tendo tirado a validação basta dar duplo clique na página, ela abrirá no explorer. Então todas as validações do client não existirão mais e o hacker poderá prosseguir no passo 2, realizando a invasão.
Solução :
Validação no client nem ao menos deveria ser chamada de validação devido a sua fragilidade. Ela é util por questões de escalabilidade, pois evita um excesso de comunicações com o servidor para que as validações tenham que ser realizadas. Porém, devido a sua fragilidade, é obrigatório que existam no servidor as mesmas validações que existem no client. Desta forma, tendo as validações nos dois locais, o hacker vai apenas perder tempo fazendo tudo que descrevemos aqui.
Porém pode ser aplicada uma solução a isso : Os servidores são capazes de identificar a origem de uma requisição, qual era a página anterior em que o usuário estava. Isso é feito com uma variável do servidor chamada HTTP_REFERRER. O valor desta variável pode ser recuperado através de linguagens rodando no servidor, tal como ASP ou PHP. Assim sendo, antes de realizar o processamento uma determinada página pode verificar se a origem dos dados foi o próprio servidor. Se não foi é porque a página foi salva em outro local e estão tentando burlar a segurança do site, assim o script identificar isso e aborta o processamento.
Solucionando Tudo
Sempre ao lidarmos com caracteres reservados de uma linguagem devemos pesquisar de que forma eles poderiam ser representados. O SQL não é uma excessão.
O apóstrofo, caracter reservado no SQL, para ser representado precisa ser dobrado. Desta forma quando o banco encontra dois apóstrofos dentro de uma string entende que o que se pretende é inserir (ou consultar, no caso) apenas um e tudo funciona corretamente.
Em ASP podemos utilizar a instrução replace para dobrar os apóstrofos digitados pelo usuário. Veja como ficaria a montagem da instrução :
sql="select * from usuarios where login='" & replace(vlogin,"'","''") & "' and senha='" & replace(vsenha,"'","''") & "'"
Desta forma não fará diferença para o código o que for digitado, o código fará a busca do que o hacker digitar como se fosse um nome de usuário e o resultado será "usuário inválido". Por isso que quando o hacker recebe a mensagem "usuário inválido" ou continua recebendo uma mensagem de erro padrão após ter tentado o ' or '1'='1 ele desiste do site, pois percebe que o site fez o tratamento dos apóstrofos corretamente.
Vale ainda destacar que muitos sites, apesar de não estarem com o bug, estão fazendo o tratamento dos apóstrofos de forma errada, demonstrando desconhecimento técnico por parte dos programadores. O fale conosco do site da Telemar é um exemplo : Não permite a digitação de apóstrofos nos campos do fale conosco. Conde D'eu não conseguiria enviar uma reclamação, nem ninguém da família D'avilla.
Espero com este artigo ter assustado suficientemente programadores e gerentes de projeto para que jamais deixem de incluir em seus projetos uma fase de checagem de segurança. Isso que demonstrei aqui é só o início, não anime-se achando que tem a solução de todos os seus problemas : Passagem de parâmetros via Get, campos Hidden, cookies, existem dezenas de pontos falhos possíveis na montagem de um site que exigem que sua segurança seja cuidadosamente testada antes de ir ao ar.

Nenhum comentário:

Postar um comentário