Terça-feira, 05 de dezembro de 2006 às 13h24

SQL Injection no PHP: O que é e como se proteger

A segurança das informações é um assunto que exige atenção especial, principalmente em se tratando de informações armazenadas em bancos de dados acessados via web.

Uma das técnicas de fraude mais conhecida pelos desenvolvedores web é a SQL Injection. Trata-se da manipulação de uma instrução SQL através das variáveis quem compõem os parâmetros recebidos por um script server-side, tal como PHP, ASP, ColdFusion e outros.

O principal motivo pelo qual deve-se impossibilitar a utilização da SQL Injection está no fato de que, através de uma simples instrução SQL, como por exemplo, uma projeção de dados, outras operações podem ser executadas, podendo impactar sobre o esquema das tabelas, os dados armazenados, e até mesmo sobre elementos do sistema operacional, tendo em vista que alguns bancos de dados permitem a execução de comandos do shell do próprio sistema operacional.

Detectando a vulnerabilidade de um sistema

Para ilustrar o conceito de SQL Injection, a seguinte simulação pode ser realizada. Imaginemos que um script de validação de acesso de usuários tenha sido desenvolvido como segue:

Nas linhas 3 e 4, as variáveis $usuario e $senha, respectivamente, recebem o conteúdo submetido por um formulário através do método POST. Eis a fonte do problema.

Suponha que a seguinte entrada tenha sido informada no campo usuário no formulário chamador do script de validação.

Logo, a query string resultante será:

Se nenhuma outra validação for realizada, o usuário mal intencionado terá efetuado login no sistema, sem ao menos informar um usuário contido na tabela. Isto foi possível pois o valor de entrada informado não recebeu o tratamento devido, sendo adicionado à instrução para ser executado. Vale ressaltar que as validações apresentadas no exemplo são apenas ilustrativas, havendo a necessidade de checagens mais eficazes para um script de validação de acesso.

Impossibilitando o uso de SQL Injection

Para que se esteja livre da utilização da SQL Injection, certas providências devem ser tomadas. Algumas das ações serão realizadas no servidor de banco de dados, outras devem ser garantidas pelo código fonte.

Deve-se tomar cuidado com a configuração do usuário que estabelece a conexão com o banco de dados. O ideal é que as permissões de acesso deste usuário estejam restritamente limitadas às funções que irá realizar, ou seja, para a exibição de um relatório, a conexão com o banco de dados deve ser realizada por um usuário com permissões de leitura e acesso somente às tabelas necessárias para sua operação.

Todos os valores originados da coleta de dados externos, devem ser validadas e tratadas a fim de impedir a execução de eventuais instruções destrutivas ou operações que não sejam as esperadas.

Um tratamento básico para a execução de querys com variáveis contendo valores informados pelo usuário:

Com a utilização da função addslashes() será adicionada uma barra invertida antes de cada aspa simples e aspa dupla encontrada, processo conhecido como escape. Se a diretiva de configuração do PHP magic_quotes_gpc estiver ativada, o escape é realizado automaticamente sobre os dados de COOKIES e dados recebidos através dos métodos GET e POST. Neste caso, não deve ser efetuado o tratamento com addslashes(). A função get_magic_quotes_gpc(), disponível nas versões do PHP a partir da 3.0.6, retorna a configuração atual da diretiva magic_quotes_gpc.

Abaixo, a query string resultante da aplicação do tratamento mencionado:

Em muitos bancos de dados, existem funções específicas para o tratamento de variáveis em query strings, o que diminui a compatibilidade do código fonte para operação com outros sistemas de banco de dados.

Outra dica importante é evitar a exibição das mensagem de erro em um servidor de aplicação em produção, pois geralmente nos erros ou alertas são exibidos caminhos de diretórios do sistema de arquivos e informações à respeito do esquema do banco de dados, podendo comprometer a segurança do sistema.

Para ocultar a exibição de erros e alertas do PHP, é necessária a configuração da diretiva display_errors para Off no arquivo de configurações do PHP.

Cabe ao desenvolvedor estar atento às possíveis brechas de segurança existentes nos códigos fonte que produz, principalmente quando o que está em jogo é um bem de grande valia: a informação. Tenha consciência. Isto evita futuras dores de cabeça e atritos desnecessários com o cliente.

20 comentários

 Diego A. Griep
05/12/2006 14h07

Muito bom seu artigo...

Já conhecia o assunto, mas é sempre bom ler a visão de outras pessoas, é bom se proteGer do sql injection.

* Dica:
Quando for postar um artigo, tenha sempre um dicionário ao lado.

[ ]'s

 Rafael Capucho
05/12/2006 16h58

Legal

Eu gostaria de saber se assim também é possivel um Injection: WHERE senha = '".$senha."'; espero respostas, Obrigado.

 Luis Fernando D. Andrade
06/12/2006 07h44

Otima iniciativa.

Ola, gostei da sua materia e parabens pela iniciativa de falar sobre seguranca embora que bem superficialmente ;).
Uma funcao muito boa 'anti sql injection' foi criada pelo Fabyo, aqui:
http://forum.imasters.com.br/index.php?showtopic=125349&hl=sql injection

Parabens e que voce continue abordando temas relacionados a essa materia.
[]s
Luis

 Igor Escobar
06/12/2006 21h56

Ai ai...

Tem gente que gosta de voltar no tempo...

 DANIEL MAFFIOLETTI
07/12/2006 07h41

De qualquer forma Parabéns!!!

Sem dúvida que este assunto é importante para iniciantes. Existem vários métodos relacionados!

 Cleison Pinter Baldin
07/12/2006 07h43

Criptografia

Outra forma de tratar o uso do SQL Injection, é obrigar o usuário a digitar login e senha, pois desta forma ninguem consegue submeter a pagina sem as dias informações.
Também utilizar criptografia na senha é muito interessante.

 Ana Claudia Nogueira
07/12/2006 08h57

Legal mas poderia ser melhor

Muito legal a sua iniciativa de falar sobre sql injection, mas ficou um pouco resumido, poderia ter sido falado mais sobre outros modos de injection

 Tiago Alexandre Vailati
07/12/2006 12h25

SQL Injection

Pessoal, tudo certo? Como foi abordado no artigo, hoje em dia, o próprio PHP já possui tratamento para dados recebidos via POST, GET e Cookies. Logo, a utilização da SQL Injection tem sido bastante dificultada. O artigo visa explanar sobre o conceito e como a SQL Injection atua, por isso, foi tratada numa visão mais superficial.

 Laércio Crestani
08/12/2006 17h09

Bom, mas!

Seria um pouco melhor um

<?
if(!isset($_POST['usuario']) || trim($_POST['usuario']) =='' || !isset($_POST['senha']) || trim ($_POST['senha'] =='')){

header('location:login.php');
exit;
}
else {
echo $_POST['usuario'];
echo $_POST['senha'];
};
?>

se chegar '' vazio, ele volta ai senão ele continua... um pouco mais lógico e ñ precisa dea verificação ON em magic_quotes_gpc no php.ini...

 Anderson Cavalcante
10/12/2006 01h05

Regular Expression

Boa a matéria,

São poucos os programadores que pensam na questão: "Segurança". Por isso tantas falhas.

Algo muito bom de utilizar, são as expressões regulares. Onde você especifica o que o campo poderá aceitar de caracter. Neste caso, entraria de a-z, A-Z, 0-9. Nada mais do que isso, dae não teria problema de substituir por contra barra para escapar o caracter. Por exemplo, posso utilizar o caracter #, que iria comentar o restante do código SQL ;)

Abraços

 Thiago Ferreira
13/12/2006 15h40

Simples e batido

O artigo não trouxe nada de novo. Explicações manjadas da web. Acho que é preciso trazer alguma coisa realmente nova ou nem escrever nada.

 Admir Tomaz
15/12/2006 22h19

Iniciantes

Serve apenas para novatos, sendo que o perigo do injetion nem foi falado, o perigo é quando fica vulnerável a ter uma tabela toda deletada pelo "drop", até um "select" de uma busca mal programada pode gerar uma perda enorme de dados.

 Érico Gustavo Kmetzsch
15/12/2006 22h56

sql injection outra forma de proteção

eu custumo usar a funcao do php htmlspecialchars() filtrando as variaveis que recebem valores do metodo POST ou GET

 Kenneth becker carletto
19/12/2006 08h39

md5()

Nao sei se esta tecnica eh muito comum, mas eu costumo usar a funcao md5($str) para login. Ela transforma $str em uma chave criptografada.
Quando cadastro usuario, salvo no banco a senha criptografada. Como esta funcao nao permite volta (nao existe um desfaz_md5()), utiliza-se a funcao tambem na senha passada por post, na ocaisao do login.

Acredito que este procedimento evite o problema do injection.

 Juliano dos Santos da Silva
31/01/2007 21h52

=D

Ae galera to gostanu até pq eu sou um novato msm na area e tento o melhor q eu posso nunca tem ninguem pra dar uma mãozinha sabem como é ¬¬

ae galera tipo se tive alguem a fim de me tirar uma duvida me add ae no msn: kcd_cs@hotmail.com

vlw gente fica cum DEUS

 Tiago Gouvêa
02/02/2007 23h44

typecast também é bom..

Outra maneira de "limitar" as entradas de dados é utilizando typecast, convertendo assim uma entrada obtida $_POST ou $_REQUEST em um tipo determinado.
Uma maneira é: $codigo=(int) $codigo;
Outra pode ser:
settype($codigo,integer);

Saudações

 Leonardo Cesar Teixeira
30/08/2007 04h11

Um solução melhor para SQL Injection

A função addslashes() é meio ultrapassada e eu não vejo porque em utilizada se tem uma função específica do PHP pra escapar aspas simples e duplas.

No caso de um simples login o addslashes() pode quebrar um galho, mas na caso de inserção de dados o addslashes() irá estragar os textos mandando eles pro banco de daodos com barras invertidas.

Então já que este site é uma das principais guias para os programadores do Brasil, eu não acho certo ensinar como evitar um problema de segurança utilizando o pior método.

A melhor função para evitar ataques de SQL Injection é usando a função mysql_real_escape_string(), ela irá escapar os dados apenas na hora da consulta e no banco de dados não irá ficar com as barras invertidas.

Eu fiz um artigo em meu blog explicando como se proteger de ataques de SQL Injection de forma eficaz e sem "destruir" os dados. E também tem um tutorialzinho ensinando a criar uma função para proteger seus scripts contra este ataque.

Para lêr o artigo acesse o endereço abaixo:

http://blog.portaldoleo.com/2007/08/28/como-evitar-ataques-de-sql-injection-no-php-e-mysql/

Mas esse artigo do Imasters está muito bom pras pessoas terem uma idéia de como ocorre um ataque de SQL Injection.

Abraços!

 Maurício Reatto Duarte
08/09/2007 18h20

Ajudou d

Nossa, eu tava tendo este problema, daí não lembrava mais como usar o anti sql-injection
Dai essa vlw ein !!

 Moacir Fernandes
10/03/2008 14h48

Não entendi a senha e login de escape

Pelo que percebi, você está dando o select validando o login e senha de escape, para que serve então o login e senha se não está sendo usado!

 Daniel Neto
17/07/2008 10h22

Ferramenta para injetar códigos

É um complemento do firefox que possibilita injetar codigo em qualquer campo do formulario, esta ferramenta é muito usada por hackers, a ferramenta pode ser baixada aqui: https://addons.mozilla.org/pt-PT/firefox/addon/6727

Cancelar resposta

Qual a sua opinião?

Faça login abaixo ou cadastre-se rapidamente.


Sobre o Autor
Tiago Alexandre Vailati é bacharelando em Ciência da Computação pela Univali/SC. Conhece as linguagens PHP, C++, Delphi, Mumps e Genexus. Possui conhecimento também em Ajax, JavaScript, Bancos de dados (MS SQLServer, PostgreSQL e MySQL) e Desing (Corel Draw, Photoshop e Photopaint).

2001 - iMasters FFPA Informática Ltda - Todos os direitos reservados.