SQL Injection, como evitar esse tipo de ataque em páginas PHP

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.

Formulário 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.

Código PHP e consulta SQL do formulário de login

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.

Formulário de Login - Imagem 1

A consulta SQL no código PHP ficaria assim

Código PHP e consulta SQL do formulário de login

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

Código PHP e consulta SQL do formulário de login

Dividi a consulta resultante da imagem acima em três outras consultas para facilitar a visualização

Código PHP e consulta SQL do formulário de login

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

Código PHP e consulta SQL do formulário de login


Com isso, a tentativa de injetar o código SQL ‘ OR 1=1 OR ”=’ resultaria em

Código PHP e consulta SQL do formulário de login

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

    • Léo em 26 de setembro de 2011 às 10:50
    • Responder

    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.

    • Alex Camargo em 13 de janeiro de 2012 às 7:48
    • Responder

    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

    1. 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.

  1. 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’ “;

      • thiago em 13 de março de 2013 às 14:28
      • Responder

      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

  2. Ainda existem muitos sites vulnerareis?

    1. 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.

  1. […] uma classe em PHP para conexão com Banco de Dados SQL Injection, como evitar esse tipo de ataque em páginas PHP […]

Deixe uma dúvida, resposta ou sugestão

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.