O que é SQL Injection?
O SQL Injection, ou injeção de SQL, é um tipo de ameaça de segurança que se aproveita de falhas em sistemas que interagem com bases de dados via SQL. O SQL Injection ocorre quando o atacante consegue inserir uma série de instruções SQL dentro de uma consulta (query) através da manipulação das entrada de dados de uma aplicação.
No caso do PHP, o SQL Injection geralmente ocorre em páginas de formulários que possuam falhas. Através disso, o atacante poderá burlar sistemas de senhas ou apagar componentes da estrutura do banco de dados (tabelas, databases, registros, esquemas e outros).
Exemplo – Formulário de login
Para demonstrar como o ataque acontece, vou usar um formulário simples de login.
A imagem abaixo mostra um exemplo clássico de um código PHP e uma consulta SQL responsáveis por efetuar uma busca de usuários no banco de dados.
Agora, imagine que eu escreva o código ‘ OR 1=1 OR ‘ ‘=’ no campo de Usuário do formulário de login e uma senha qualquer.
A consulta SQL no código PHP ficaria assim
Pensando um pouco sobre a consulta SQL resultante mostrada na imagem acima. O que você acha que aconteceria se ela fosse executada?
Ela simplesmente retornaria todos os usuários do banco, o resultado dela seria exatamente igual à
SELECT usu_in_id, usu_st_nome, usu_st_login, usu_st_email FROM control.tbl_usuario
e o atacante teria acesso ao sistema.
Imagine então que o o atacante seja um pouco mais malicioso, ao invés de entrar no sistema, ele queira apagar a tabela de usuários. Então ele só teria que escrever ‘; DELETE FROM tbl_usuario; SELECT * FROM tbl_usuario WHERE ‘ ‘=’ no campo de Usuário e então a consulta resultante ficaria
Dividi a consulta resultante da imagem acima em três outras consultas para facilitar a visualização
Como evitar esse tipo de ataque em páginas escritas em PHP
Olhando o exemplo do formulário de login acima, você consegue chegar a uma solução do problema?
Se você pensou em substituir o caractere ‘ por um outro qualquer, está no caminho certo.
O jeito mais simples é usar a função nativa do PHP addslashes($str) para substituir o caractere ‘ por \’ vindos de campos de texto do formulário. Isso deixaria o nosso código do formulário de login assim
Com isso, a tentativa de injetar o código SQL ‘ OR 1=1 OR ”=’ resultaria em
O Problema de usar a funçãoaddslashes($str) é que você não poderá esquecer de usá-la para nenhum campo de texto do formulário, ou seja, se o seu formulário possuir 50 campos de texto, você terá que filtrar todos eles.
Existe uma maneira de fazer com que o interpretador PHP filtre automaticamente todos os campos de formulários, substituindo o caractere ‘ por \’. Assim, não será mais necessário usar a função addslashes($str).
Para filtrar automaticamente os campos de formulários, substitua magic_quotes_gpc = Off por magic_quotes_gpc = On no arquivo php.ini (arquivo de configuração do interpretador PHP).
Com esses cuidados, o problema de segurança está resolvido?
Não. Ainda precisamos tomar cuidado com os campos numéricos dos formulários.
Eu não vou entrar muito nesse assunto, mas meu conselho é sempre verificar se os dados vindos de campos numéricos são realmente numéricos usando a função is_numeric($var)
if(is_numeric($in_idade))
{
//executa o código
}
Essas são as dicas que e tenho para dar sobre como se proteger de ataques do tipo SQL Injection. Espero ter ajudado vocês.
Qualquer dúvida ou sugestão, usem a área de respostas no final do post.
7 comentários
1 menção
Pular para o formulário de comentário
Excelente post, faz algum tempo que não programo em php e essa foi uma dica crucial para proteger minhas paginas, vou sempre dar uma passada aqui para conferir novidades.
Grande post! A dica:
if(is_numeric($in_idade))
{
//executa o código
}
é muito boa para campos que pesquisam somente pelo id no banco.
Abração
Autor
Obrigado Alex. Se você tiver alguma sugestão ou crítica sobre esse ou outro post do blog, sinta-se a vontade para escrever ai na área de perguntas e respostas.
Tarcísio, essa função pode ser utilizada também quando a query buscar o valor de um Get, certo?
Veja o exemplo abaixo:
$idget = $_GET[‘id’];
$id = addslashes($idget);
$sqlalunos = “SELECT * FROM aluno WHERE idaluno= ‘$id’ “;
Não.. qdo for usar $_GET pra inteiros, é só usar (int) $_GET[‘id’];
repare no (int) antes do $_GET[]
ele transforma qualquer tentativa de sql injection em inteiro
?id=5′
ficaria 5 normal, e o invasor não conseguiria aplicar o sql injection
Ainda existem muitos sites vulnerareis?
Autor
Todos os dias, novos sites são criados e acredito que alguns deles possuem essa vulnerabilidade. Acho que o número de sites vulneráveis só cresce.
[…] uma classe em PHP para conexão com Banco de Dados SQL Injection, como evitar esse tipo de ataque em páginas PHP […]