SQL Injection – Como evitar ataques de injeção SQL

SQL Injection – Como evitar ataques de injeção SQL

Você sabe como evitar ataques de SQL Injection? Esse tipo de ameaça aproveita-se de falhas de interação com o banco para inserir ou manipular consultas entre a aplicação e a base de dados, permitindo que diversas ações sejam tomadas pelos atacantes, desde descobrir um usuário e senha, até ter total controle do seu banco de dados.

O SQL Injection aparece regularmente entre os TOP 10 da OWASP, infelizmente ele ainda é uma vulnerabilidade muito presente em milhares de aplicações e colocam em risco todo o seu negócio, se você é o gestor ou proprietário de uma empresa, não vai querer que uma pessoa mal intencionada tenha acesso a toda a base de dados do seu negócio e comprometa não somente a sua companhia, como o seu cliente, não é mesmo?

Se você é um desenvolvedor, não vai desejar que alguém de fora venha colocar abaixo todo o seu trabalho ou lhe crie enormes dores de cabeça porque ganhou acessos indevidos com ataques desse tipo.

Por esse motivo, sempre vale verificar como prevenir as vulnerabilidades de Injection SQL, você verá que evita-las é apenas uma questão de boas práticas, tornando muito mais simples e barato as evitar do que corrigir.

Como ocorre um SQL Injection?

Antes de partirmos para a explicação de prevenção, precisamos entender como um SQL Injection pode ocorrer. Para isso vamos usar uma tela de login, que para ser construída utilizou o seguinte trecho de código:

String usuario=request.getParameter(“admin”);
String senha=request.getParameter(“123”);
SELECT usuario from usuario where usuario=’”+usuario+”’ AND usuariosenha =’”+senha+”’;

No código acima temos os parâmetros direto no código SQL para efetuar a validação de dados, o problema é que dessa forma torna-se possível colocar informações adicionais no campo de usuário e senha para que sejam tratadas pelo SQL. O atacante poderia colocar no lugar da senha a condição or para pular a validação de senha, veja o exemplo:

String usuario=request.getParameter(“admin”);
String senha=request.getParameter(“ ' or '='”);
SELECT usuario from usuario where usuario=’”+usuario+”’ AND usuariosenha =’”+senha+”’;

Veja que interessante, o atacante não faz a mínima idéia da senha de login, porém em seu lugar, inseriu um conjunto de instruções que dizem para a validação que a senha será igual a zero, fazendo com que ela seja verdadeira e conceda o acesso, mesmo ele não tendo a real senha do usuário.

Através dessa manipulação, ele conseguiria ir além de obter o sucesso do login, poderia continuar completando sua query para descobrir até mesmo o nome do banco e demais elementos presentes nessa tabela. 

O mais assustador é que esse exemplo foi baseado em um trecho de código compartilhado em um fórum de desenvolvedores, ou seja, isso ainda é uma prática comum e esse tipo de abordagem em diversos sistemas acaba justificando o porquê do SQL Injection estar constantemente entre os TOP 10 da OWASP, isso sem entrar em detalhes na fragilidade desse tipo de autenticação, uma vez que não faz parte do tema desta matéria e futuramente falaremos sobre um processo de autenticação seguro.

Práticas de prevenção de SQL Injection

Reconhecimento | Observatório Social de Florianópolis

O primeiro passo para prevenir-se de um ataque desse tipo é efetuar a verificação de entrada do usuário, este é o principal vetor de ataque para o SQL Injection e precisa ser controlado e examinado.

Validação de entrada

Este processo consiste em garantir que o tipo de input inserido pelo usuário é permitido e previsto pelo seu sistema, mas lembre-se, a validação de dados não deve ocorrer apenas em campos de digitação, mas em qualquer situação que permita a entrada de dados.

Usar expressões regulares para garantir o seu formato, comprimento e demais características esperadas é um importante caminho. Para o Java é possível usar classes como o java.util.regex para esse trabalho, se você estiver no mundo mobile, vale dar uma olhada nessa documentação do Flutter, onde a Google mantém um passo a passo de como efetuar essa validação em seu framework.

Entre as verificações, nunca esqueça de validar o tipo do dado permitido, se valores nulos serão permitidos e se o dado pode ser omitido.

Consultas parametrizadas

Essa boa prática permite que o código e os dados de entrada sejam diferenciadas, você encontrará sua abordagem também com o nome de prepared statements.

Ao separar os parâmetros enviados pelo usuário da query, evitamos a alteração da intenção e evitamos problemas com SQL Injection. Mesmo que o usuário mal intencionado, optasse por colocar um parâmetro ‘ or ‘=’, como no código de login que demos de exemplo, isso seria interpretado como uma string e não causaria a alteração na validação.

Em java, podemos usar a instrução PreparedStatement para fazer esse tratamento. Vamos aproveitar aquele exemplo que pegamos na internet e dar uma olhada em como ele poderia ficar ao usar o PreparedStatement e prevenir usuários mal intencionados. 

String sql=Insert into accounts(usuario, usuariosenha) values (?,?);
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, usuario);
stmt.setString(2, senha);
stmt.execute();

Independente da linguagem que esteja escrevendo sua aplicação, as validações de entrada combinadas com as consultas parametrizadas ajudam a prevenir ataques de SQL Injection em seu sistema. É muito importante lembrar que eles não ocorrem apenas em um campo de login e senha, usamos-o como exemplo devido a sua fragilidade, porém campos de pesquisa, formulários e qualquer outro local que possibilite uma entrada de dados e gere uma consulta na base, pode ser um alvo.

Lembre-se, a utilização de um WAF em sua aplicação é uma boa prática e ajudará em tentativas de SQL Injection, mas se não tiveres boas práticas no desenvolvimento de sua aplicação, não há remediação que conseguirá evitar possíveis danos.

Enable Notifications    Ok No thanks