SQL Injection – você está protegido?

Caríssimos(as), em primeiro lugar gostaria de pedir desculpas pela falta de posts neste último mês. Desculpas especialmente aos leitores assíduos que escreveram cobrando atualizações. Tive um mês extremamente corrido, com muitas obrigações a cumprir sem tempo de atualizar o blog – e tocar o CFUG-SP!mas essa é uma outra história 😉. Espero que daqui até o fim do ano as coisas fiquem mais calmas e que eu possa postar mais vezes por aqui.

Dando continuidade aos posts sobre segurança em aplicações ColdFusion, tratarei de um assunto que não envolve apenas ColdFusion, mas toda e qualquer linguagem server-side (PHP, ASP, JSP, etc). Trata-se do SQL Injection. Se você já conhece esta vulnerabilidade, a leitura é válida pois esse tipo de discussão é rara na Internet brasileira. Mas se você nunca ouviu falar a leitura é obrigatória. Terminando-a provavelmente você terá que sentar a bunda na cadeira e rever quilômetros de código inseguro que você pode ter gerado. Procurarei ser o mais suscinto possível e atacar a questão de vez, com exemplos, sem muita enrolação e apresentações. Se você ainda ficar com alguma dúvida, sugiro que poste-a na lista CF-Brasil. Eu e muitos outros programadores CF terão prazer em ajudá-lo.

SQL Injection, literalmente falando, é o ato de “injetar” código SQL não esperado numa aplicação com fins não muito amigáveis. Apenas para esquentar: você já tentou acessar uma página dinâmica dessa forma:

EXEMPLO 1
http://www.site.com.br/produtos/produto?id=77;DELETE FROM produtos

Ou ainda criou um formulário deste tipo:

EXEMPLO 2
<FORM ACTION=”http://www.servidor_atacado.com/busca.cfm” METHOD=”post”>
<INPUT TYPE=”hidden” NAME=”string_busca” VALUE=”;DROP TABLE noticias”>
<INPUT TYPE=”submit”>
</FORM>

Ou ainda pior:

EXEMPLO 3
<FORM ACTION=”http://www.servidor_atacado.com/login/logar.cfm” METHOD=”post”>
<INPUT TYPE=”hidden” NAME=”username” VALUE=”qqcoisa”>
<INPUT TYPE=”hidden” NAME=”senha” VALUE=”;AND 1=1″>
<INPUT TYPE=”submit”>
</FORM>

Se não tentou, deveria fazê-lo em suas aplicações ColdFusion (ou qualquer outra linguagem) para ver se estas estão seguras.

Note a presença de códigos SQL “extras” na aplicação. Soa alguma coisa comum à SQL? Pois é exatamente isso. Na medida em que a aplicação usa a tag <CFQUERY> para acessar o banco de dados e o faz recebendo informações (via form, url, etc) do usuário, ela pode estar vulnerável. Veja o caso do exemplo 1, onde o arquivo “produto.cfm”, faz uma chamada ao BD da seguinte forma:

SELECT * FROM noticias
WHERE NoticiaID=#url.id#

Com a injeção de código SQL teríamos:

SELECT * FROM noticias
WHERE NoticiaID=77 ;
DELETE FROM noticias

Note o ponto-e-vírgula, que é o separador de comandos para o SQL Server e Access (se não me engano). Em outros bancos de dados você poderia usar simplesmente espaço, o sinal de mais (+), etc, basta consultar. Boom! Sua tabela de notícias foi para o limbo e ai de você se não tiver backup dela. Sem falar no tempo fora do ar até restabelecer todos os serviços…

Mas o problema não se limita à apagar tabelas e ficar fazendo esse tipo de brincadeira de criança (para não usar o termo lammer). Você já pensou em criar um usuário com previlégios de administrador no BD que mantém uma determinada aplicação? Sem apagar nada, sem esforço, conectar-se e roubar o que lhe importa. Pois isso também é possível. O SQL Server, por exemplo, possui uma série de procedures que são usadas para se criar usuários, alterar senhas, aumentar o nível de acesso de determinados usuários, entre tantas outras. Não vou entrar nestes detalhes pois esse não é o objetivo deste post, porém deixo um alerta: JAMAIS configure uma datasource usando uma conta com previlégios de administrador do BD (falarei mais a respeito abaixo).

As possibilidades de ataque e roubo de informações através da técnica de SQL Injection são inúmeras e o pior disso tudo: até os melhores programadores não conhecem tal vulnerabilidade.

Muito se discute sobre a segurança de um determinado sistema operacional, fala-se que o Linux é mais seguro que Windows, fala-se que o firewall XYZ analisa melhor pacotes, que a criptografia 128 bits é “quebrável”, que o site “DamnGood.com” está imune à ataques do tipo DDoS, blá, blá, blá, e esquece-se do fundamental: a aplicação. Sim, a aplicação… àquela que todos põe a mão, àquela que é acessível pela porta 80 do TCP/IP e que tem uma redundância de 100%…. Redundância de 100% para permitir que nenhum engraçadinho fique de fora da farra… ;o)

Agora a boa notícia: o SQL Injection é uma vulnerabilidade facilmente contornável com o simples e velho CÓDIGO SEGURO. Sim, pensar em segurança (como já disse), deve fazer parte da sua rotina de programação. Você deve ter a sensibilidade suficiente para saber que está lidando com uma parte de código importante que poderá ser burlada por alguém que conheça a lógica básica de programação ou até mesmo obtenha alguma informação previlegiada. Informação priveligiada? Ué, mas para obtê-la eu não preciso invadir os sistemas de outra maneira, mais “profissional”? Talvez conseguir uma senha no banco de dados para poder ver suas tabelas, obter acesso ao código fonte do “.cfm” para saber como está estruturada uma query que desejo atacar???

Néca de catibiriba, isso é muito fácil de se obter apenas fazendo a aplicação receber valores que ela não está esperando (e torcer para que o programador seja bem descuidado também). Veja um exemplo tolo (clique no link abaixo):

http://www2.sabesabe.com.br/sejaesp_todas_sabe.cfm?id_sequencial=

No exemplo acima podemos obter, literalmente “de bandeija”, toda a informação necessária para se efetuar um ataque do tipo SQL Injection. Aqui vemos o tipo de banco de dados usado, bloco SQL, nome de tabelas, nome de campos, etc, etc. Isso dá a deixa para eu contar qual é a regra número 1 para se safar de ataques SQL Injection (e tantos outros existentes):

1) Jamais deixe amostra os erros da sua aplicação! Deslige o debug info! Estes erros interessam somente à você e a ninguém mais, por isso trate de usar tratamento de erros ou então deixar o servidor CF fazer isso por você por meio do Site-wide Error Handler;

Na seqüência algumas outras (mais diretamente aplicadas ao ColdFusion). Veja e aprenda mais com as referências que dou no final do post.

2) Valide os dados que a sua aplicação recebe. A melhor maneira de se fazer isso é através do uso de stored procedures. Se não puder usar stored procedures ou seu uso não faça sentido, use a tag <CFQUERY> com segurança! O melhor é receber e passar para o BD os valores de strings pela tag <CFQUERYPARAM>. Veja o exemplo abaixo:

SELECT * FROM noticias
WHERE NoticiaID=<CFQUERYPARAM VALUE=”#url.id#” CFSQLTYPE=”CF_SQL_INTEGER”>

Isso inclusive aumenta a performance da sua query pois o CFServer já saberá de antemão qual é o tipo de dado a ser enviado ao BD.

3) Use um user específico para cada datasource que você tem nesse servidor. Eu costumo criar, para uma mesma aplicação/banco de dados, duas datasources distinas. Nas minhas aplicações de notícias, por exemplo, eu tenho sempre o user “noticias_reader” e o user “noticias_writer”. Um poderá (com base nas permissões de acesso do próprio DB) apenas ler e o outro ler e escrever. Dessa forma terei que me preocupar em validar apenas as queries que façam alterações e inserções no BD, já que qualquer operação de alteração ou deleção “forçada” na primeira datasource será negada pelo banco de dados. Em sites abertos ao público, temos tipicamente apenas operações de leitura de dados. Já a alteração/inserção ocorre em sistemas internos (os famosos “admins”), o que já elimina uma camada de vulnerabilidade. Mas mesmo assim SEMPRE VALIDE as entradas de dados da sua aplicação;

4) Jamais use uma conta com previlégios de administrador para conectar-se ao banco de dados (a conta sa do MSSQL, por exemplo). Além de tornar a sua aplicação/vulnerável, você poderá estar comprometendo TODO um sistema. O mesmo é válido para a “trusted connection”. Normalmente a conta usada nesse tipo de autenticação é a de Administador.

5) Para finalizar, a velha máxima: “Quando tudo mais falhar, tenha sempre um backup em mãos… ” ;o)

Abaixo segue alguns links interessantes sobre o assunto (agradeço pelos comentários de Rui Dias Quintino). Leia-os para se saber melhor. Lembre-se de que o seu pescoço – e o seu emprego por tabela – está em jogo em se tratando de segurança!!

O bom e velho Google e seus resultados maravilhosos…
Uma coletânea de 18 mil referências ao assunto.

Guesswork Plagues Web Hole Reporting
Uma das últimas vítimas de um ataque deste tipo. Resultado: acesso indevido à base de dados de clientes da Guess (incluindo 200.000 números de cartões de crédito).

SQL Injection Whitepaper – Spi Dynamics
Bastante completo. Para começar.

Advanced SQL Injection in SQl Server Applications
Direccionado apenas para o SQL Server, que como por esta altura já devem saber é uma aplicação extremamente sensível neste campo.

Guarding your Web Site against SQL Injection Attacks
Depois de ler os anteriores talvez este não acrescente muito. Fortemente ligado à plataforma Microsoft.

SQL Injection FAQ
Um FAQ bem resumido, para aqueles que não têm muito tempo.

OWASP – Open Web Application Security Project (Direct SQL Command Injection)
Um dos melhores sites a este nível. E sendo assim não podia deixar de mencionar este tipo de vulnerabilidades.

SQL Injection Walkthrough
Mais um que apanhei no SecurityTeam.


28 Comments on “SQL Injection – você está protegido?”

  1. Leandro Marques disse:

    Ola, sou administrador de um site que tem sido atacado frequentemente por um “Lammer”, usando esse SQL injection. So que meu site foi feito em asp e nao em CF. gostaria de saber mais infomações de como me proteger no asp ou se puder me indiqui algum lugar que fale sobre isso

  2. Barriga disse:

    Bloqueie os caracteres “;” , “‘” e “–” já resolve.

  3. Leonardo disse:

    Bom…

    Fiz um teste em BD Access e não funcionou. Para os usuários de Access, PODEM FIQUAR TRANQUILOS !

  4. Celão disse:

    então quer dizer que esse esquema de SQL Injection não funciona com banco de dados access???

    valeu…

  5. para leonardo disse:

    Leonardo, se eu fosse vc nao ficaria tão tranquilo.

  6. Jocelino Gonçalves disse:

    Está ocorrendo exclusões de pastas no meu Site. O suporte diz que ser um “lammer”, usando comandos do tipo “SQL injection”. Pelo que eu li acima esses comandos são para Banco de dados, isso também é possível com pasta?

  7. Ulisses disse:

    O Access + asp também está vulnerável ao ataque do tipo SQLInjection, as únicas coisa que ele não aceitará é o “–” (comentário), o drop, o alter e alguns outros, mas nesses casos ainda dá pra fazer algumas coisas, digamos que você quer entrar como administrador em um site pode notar o seguinte.
    1 – Normalmente o registro referente ao administrador é o primeiro registro do banco de dados, ou seja, é mais fácil entrar como administrador do que como usuário normal.
    2 – Em um campo com login e a senha você poderá fazer o seguinte
    Login = ‘ or ‘1’ = ‘1
    Senha = ‘ or ‘1’ = ‘1
    3 – Normalmente você entrará como administrador, não se esqueça de não fechar o último apostrofe, pois o próprio código em asp fará isso por você.
    4 – Uma maneira de evitar que o macete acima aconteça é a seguinte regra, nunca deixe a string sql decidir nada, é melhor que você selecione o registro cujo login é o tal e depois usando um if verificar se a senha dada é a mesma do banco de dados.

  8. WAKKO disse:

    Já tive alguns problemas com SQLInjection e na época custei a descobrir o que era!

    Mas o post ficou bem colocado!
    Vlw!

  9. wander disse:

    isso funciona no oracle??

  10. Xvascaina disse:

    create table tempdb..passwords( pwd varchar(255) ) bulk insert tempdb..passwords from ‘c:temppasswords.txt’ select name, pwd from tempdb..passwords inner join sysxlogins on (pwdcompare( pwd, sysxlogins.password, 0 ) = 1) union select name, name from sysxlogins where (pwdcompare( name, sysxlogins.password, 0 ) = 1) union select sysxlogins.name, null from sysxlogins join syslogins on sysxlogins.sid=syslogins.sid where sysxlogins.password is null and syslogins.isntgroup=0 and syslogins.isntuser=0 drop table tempdb..passwords Page 25

  11. Marcio Hubner disse:

    Interesante mas eu trabalho com aspx ja tenho conecimento sobre o sql injection (ja aplikei alguns) como posos me protejer?

  12. Adriano disse:

    Olá,
    Alguém sabe se existe algum similar ao addslashes do PHP no ASP?

    Valeu!

    Adriano

  13. Marcos Queiroz Galvão disse:

    Alguem poderia complementar a dica abaixo com os comandos necessários para bloquear oa caracteres seguintes :
    Por Leandro Marques , agosto 27, 2003 10:00 AM

    Bloqueie os caracteres “;” , “‘” e “–” já resolve.

  14. Portugal disse:

    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    Table simples, para exemplo de como evitar todo o tipo de sql injection no login do utilizador

    A tabela utilizadores deverá ter pelo menos as seguintes colunas:

    [username]
    username

    [password]
    encrypted password

    [usercode]
    encrypted usename

    _______________________
    Nos exemplos vou usar para encriptar apenas a função md5() e só com uma passagem.
    Por questões de segurança, extra, deves sempre adicionar texto à palavra, depois passar pela função md5(),
    e mais do que uma vez
    _______________________

    código (não é código puro, mas instruções):

    $user_code=md5($_POST[‘username’]);

    QUERY = SELECT * FROM username WHERE usercode = $user_code;

    Se o numero de rows for igual a 1:
    guardar o username tirado da tabela numa variavel $username;

    $password=md5($_POST[‘password’];
    SELECT username FROM username WHERE username = $username AND password = $password;

    SE o numero de rows for igual a 1;
    $_SESSION[‘username’]=$username

    ____________________________

    Acho que dá para entender. Não sei se este procedimento já é usado, mas penso que é perfeito a nivel de segurança,
    pelo menos até prova em contrário.

    Porquê? Os dois valores que o utilizador passa, nomeadamente o username e a password, sao encriptados, logo nenhum
    código SQL vai chegar à base de dados
    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

  15. Portugal disse:

    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    Table simples, para exemplo de como evitar todo o tipo de sql injection no login do utilizador

    A tabela utilizadores deverá ter pelo menos as seguintes colunas:

    [username]
    username

    [password]
    encrypted password

    [usercode]
    encrypted usename

    _______________________
    Nos exemplos vou usar para encriptar apenas a função md5() e só com uma passagem.
    Por questões de segurança, extra, deves sempre adicionar texto à palavra, depois passar pela função md5(),
    e mais do que uma vez
    _______________________

    código (não é código puro, mas instruções):

    $user_code=md5($_POST[‘username’]);

    QUERY = SELECT * FROM username WHERE usercode = $user_code;

    Se o numero de rows for igual a 1:
    guardar o username tirado da tabela numa variavel $username;

    $password=md5($_POST[‘password’];
    SELECT username FROM username WHERE username = $username AND password = $password;

    SE o numero de rows for igual a 1;
    $_SESSION[‘username’]=$username

    ____________________________

    Acho que dá para entender. Não sei se este procedimento já é usado, mas penso que é perfeito a nivel de segurança,
    pelo menos até prova em contrário.

    Porquê? Os dois valores que o utilizador passa, nomeadamente o username e a password, sao encriptados, logo nenhum
    código SQL vai chegar à base de dados
    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

  16. Evandro disse:
  17. Evandro disse:
  18. Jéter Ornelas disse:

    Ae gelerar uma ótima materia de se proteger contra sql em página asp:

    nome = Trim(Server.URLEncode(Request.Form(“username”)))
    senha = Trim(Server.URLEncode(Request.Form(“senha”)))

    Abraço!

  19. tyerry disse:

    como e onde baxo o SQL injection. porfavor me mandem. xD

  20. lellis disse:

    Muito bom o artigo, parabens. Me mostrou algo que desconhecia completamente.

  21. Todeboa disse:

    ei Jéter Ornelas , você não leu a matéria, você está achando que SQL Injection é um programa??? Deve ser outro lammer querendo uma receita de bolo. Vai estudar SQL, que vc ganha mais.

  22. Spank' disse:

    Nossa onde eu baixo sql Injection foi o pior uhaua

  23. ana disse:

    como evitar sql injection usando stored procedure

  24. André disse:

    Boa noite pessoal!

    Sou programdor J2EE e me interessei muito por essa área de segurança. Inclusive vou fazer o meu TCC a respeito das invasões e vulnerabilidades da porta 80.

    Se possível gostaria que os Senhores me indicassem alguns materiais para estudo.

    Estou tentando aplicar este código

    select * from tbl_contatoemp where operPabx = 24 ; delete from tbl_contatoemp

    que vi no tutorial logo acima e está instrução de delete não apaga as informações.

    Estou fazendo teste no MySql..

    Obrigado

  25. O Todeboa o meu comentário foi esse aqui ó:
    Ae gelerar uma ótima materia de se proteger contra sql em página asp:

    nome = Trim(Server.URLEncode(Request.Form(“username”)))
    senha = Trim(Server.URLEncode(Request.Form(“senha”)))

    Abraço!

    o que pede pra downlod é do tyerry

    presta atenção antes de citar nomes e nomes errados ainda por cima cara da uma olhada na diagramação da página o vc vai ver q cometeu um engano!

    flw

  26. eduardo disse:

    ana te amo

  27. Alexandre disse:

    Estou realizando uma monografia com este tema e sinto falta de atingir um material bibliográfico de qualidade. Você ou alguém poderia me informar algumas fontes interessantes? Muito obrigado.

    Alexandre Silva
    São Paulo
    http://www.monografiaalpha.com.br

  28. skloktigas disse:

    tipo decobri usuario e senha eu sei mais como faço pra entra no banco de dados do site ate a parte de usuario e senha ????
    ex: se o endereço do site for esse oq coloco pra chegar ate a parte de usuario e senha e no banco de dados

    http://www.muaustin.rg3.net/

    o q coloco no endereço ?????