Palavra:   

Revista PHP / Segurança

Josimar Finamore

Técnico em Microinformática – Cursando Sistema de Informação (UNILESTE MG)) Programador Junior do Unileste MG

Protegendo seu LOGIN contra SQL's Maliciosos

Olá pessoal...

A quanto tempo eu não posto...
Hoje nos vamos tratar de proteger nossas páginas de SQL injections. Aquelas instruções maliciosos que os nossos “amigos” programadores de má índole ficam inserindo em nossas base.

Bom. É uma validação simples. E temos que fazer isso, senão eles ficam como programadores de má índole e nós de meia tijela nem....

Bom, o código é simples, segue o SQL do banco para levantarem uma base simples de teste. Vide em anexo.
  1. CREATE DATABASE `sqlmal`;
  2.  
  3. USE `sqlmal`;
  4.  
  5. CREATE TABLE `usu` (
  6. `usu` varchar(8) NOT NULL DEFAULT '',
  7. `senha` varchar(255) DEFAULT NULL,
  8. PRIMARY KEY (`usu`)
  9. ) TYPE=MyISAM;
  10.  
  11. INSERT INTO `usu` VALUES ('josimar','senha');
  12. INSERT INTO `usu` VALUES ('usuario','123');
  13. INSERT INTO `usu` VALUES ('sql','mal');
  14.  
E abaixo o código em PHP para explicar e testar a solução, veja as explicações das linhas.
  1. $sql="select senha from usu where usu='".$_POST["txt_usu"]."';";
Seleciono a senha do usuário que ele informou, se ele tiver digitado por exemplo ‘ or ‘1 vai trazer todo mundo.
  1. $qnt=count($res);
Conto quantos registro foram selecionados no sql. Aqui é a chave do negocio pois SQL injections em sua maioria trazem muitos registros da base
  1. if (($res[0]==$_POST[“txt_pass”])&&($qnt==1))
A perola e a validação estão aqui. A senha que eu trouxe da base tem que ser igual ao que o cara digitou (tchau SQL maldoso) e se a consulta me retorna apenas um registro. Se isso aconteceu é por que não é SQL malicioso ou é um bem feito...(RISOS) pois estamos num mundo que as soluções de segurança evoluem rápido. Mas o problemas de segurança mais rápidos ainda.

Espero que tenha sido de proveito a vocês. Até o próximo...
Eu devo começar a abordar a segurança no PHP

FONTE DA PÁGINA EM PHP (antisqlinjection.php)
  1. <?php
  2. //Copnecto-me ao banco
  3. $servidor="localhost";
  4. $usuario_bd="root";
  5. $senha_bd="";
  6. $banco="sqlmal";
  7. $con=mysql_connect($servidor, $usuario_bd, $senha_bd);
  8. mysql_select_db($banco,$con);
  9. //Desenvolvimento da página
  10. if ((!isset($_POST["txt_usu"]))&&(!isset($_POST["txt_pass"]))) //Testo se não existe USUARIO E SENHA no POST
  11. { //Caso não exista mostro o formulário para entrada de dados
  12. ?>
  13. <form method="POST" action="antisqlinjection.php">
  14. <center>
  15. <h1>Informe Usuário e Senha Para ter Acesso ao Sistema XPTO</h1>
  16. <b>Usuário</b><input type="text" size="20" name="txt_usu"><BR>
  17. <b>Senha</b><input type="password" size="20" name="txt_pass"><BR><BR>
  18. <input type="submit" value="Entrar">
  19. <input type="reset" value="Limpar">
  20. </center>
  21. </form>
  22. <?php
  23. }
  24. else
  25. {
  26. if (($_POST["txt_usu"]=="")||($_POST["txt_pass"]==""))
  27. { //testo se uma das variaveis veio em branco
  28. ?>
  29. <center>
  30. <h1><font color="#FF0000">Dados Incorretos</font></h1><BR><BR>
  31. <a href="antisqlinjection.php">Voltar</a>
  32. </center>
  33. <?php
  34. }
  35. else
  36. {
  37. $sql="select senha from usu where usu='".$_POST["txt_usu"]."';";
  38. $qry=mysql_query($sql,$con);
  39. $res=mysql_fetch_row($qry);
  40. $qnt=count($res);
  41. if (($res[0]==$_POST["txt_pass"])&&($qnt==1))
  42. {
  43. ?>
  44. <center>
  45. <h1>LOGADO</h1><BR>
  46. Se você entrou com SQL injection me ensine o que fez. josimarfinamore@gmail.com
  47. <BR><BR>
  48. <a href="antisqlinjection.php">Voltar</a>
  49. </center>
  50. <?php
  51. }
  52. else
  53. {
  54. ?>
  55. <center>
  56. <h1>ERRO</h1><BR>
  57. Esta página trata os SQL injection mais comuns. qualquer dúvida josimarfinamore@gmail.com
  58. <BR><BR>
  59. <a href="antisqlinjection.php">Voltar</a>
  60. </center>
  61. <?php
  62. }
  63. }
  64. }
  65. ?>

Opções de Interação

Comentários

Complementando...
Por: Arnaldo, 31/08/2009   13:50:09
Acho que os colegas já enumeraram todos os problemas referenteas ao código acima. Eu gostaria apenas de completar dizendo que a senha cadastrada na base de dados deve estar criptografada com com algum algorítimo assimétrico + salt password e que também é uma boa prática para evitar o sql injection o uso de bindParam do PDO. Abraço galera!
Não Faria pensando apenas no login
Por: Mário, 13/03/2009   08:59:08
Na minha opinião, a proteção não deve estar apenas na hipótese de uma pessoa querer se logar sem ter o cadastro.
Creio que deve-se pensar mais a fundo no que o usuário malicioso queira fazer.
Existem muitos casos onde o usuário malicioso envia instruções SQL nos campos de digitação que a página disponibiliza. Creio que a segurança deve se extender até este ponto ou mais além.
Com certeza , addslashes é mais seguro que sua proposta.
Fraco
Por: Julio, 11/09/2008   19:02:46
Muito trabalho pra pouco resultado, o mais correto é o mysql_real_escape_string()

http://www.php.net/manual/en/function.mysql-real-escape-string.php
fraco esse post
Por: Carlos, 22/08/2008   11:54:16
Cara seguinte a melhor forma de se proteger é usar a funçao do php mesmo que é mysql_real_escape_string() pois é mais completa que a addslashes

como o rafael falou acima esse seu codigo nao faz nada apenas deu mais trabalho em verificar uma entrada de dados que pode acabar com o seu banco sem contar
que se voce colocar
' or 1='1 ja ta dentro do sistema

um abraço

os codigos postados aqui poderiam ser avaliados antes de postar porque senao vira terra de ninguem e codigos como esse ensinao coisas erradas, sem contar que é um codigo bem maior do que podemos usar para uma verificação simples de senha

abraçoo
falho demais
Por: Micael, 05/08/2008   13:57:06
1º: se resolve muito mais facilmente usando o addslashes
2º como o Rafael disse, tu não evita o sql injection, soh valida os dados depois. Pode deletar o banco, validar de varias formas.

acho o conteudo deste site muito fraco, cheio de falhas de segurança. o pessoal tem que cuidar mais antes de publicar material.
Segurança falha
Por: Rafael, 31/07/2008   06:45:49
Este seu metodo de proteção é extremamente falho. é possivel até mesmo deletar seu banco de dados. colocando uma aspa simples no campo "txt_usu", qualquer comando apos , será executado, por exemplo

' and drop database sqlmal --

nao testei, mas isso, ou algo proximo, fura seu sistema facilmente