O que é SQL Injection e como tratar

A SQL Injection (ou injeção de SQL) é um tipo de ataque que torna possível executar declarações SQL maliciosas.

Estas declarações controlam um servidor de banco de dados por trás de uma aplicação.

Uma pessoa má intencionada pode usar vulnerabilidades de seu sistema para contornar as medidas de segurança de sua aplicação.  Com SQL Injection, também é possível adicionar, modificar e excluir registros no banco de dados.

Por que se preocupar

Como você sabe, SQL é uma linguagem de consulta que foi projetada para gerenciar dados armazenados em bases de dados relacionais.  Muitas aplicações web armazenam todos os dados em bases de dados SQL. Em alguns casos, você também pode usar comandos SQL para executar comandos do sistema operacional.

Sabendo de todos os privilégios, um ataque de injecção SQL bem sucedido pode ter consequências muito graves.

Uma vulnerabilidade de injeção SQL pode afetar qualquer site ou aplicação web que usa um banco de dados SQL como MySQL, Oracle, SQL Server, ou outros.

O atacante podem usar a técnica para obter acesso não autorizado aos seus dados sensíveis: informações do cliente, dados pessoais, segredos comerciais, propriedade intelectual, e muito mais. Os ataques de injeção SQL são uma das mais antigas, prevalentes e mais perigosas vulnerabilidades de aplicações web.

Como funciona um ataque de injeção SQL

Para fazer um ataque de injeção SQL, um atacante deve primeiro encontrar entradas vulneráveis de uma aplicação web, normalmente associada a um formulário com dados de entrada.

Por exemplo: Uma página web ou aplicação web que tem uma vulnerabilidade de injeção SQL usa essa entrada de usuário diretamente em uma consulta SQL, realizando procedimento de concatenação.

O atacante pode criar conteúdo de entrada com fins maliciosos. Depois que o atacante envia este conteúdo, comandos SQL podem ser executados no banco de dados.

Os atacantes podem usar injeções SQL para encontrar as credenciais de outros usuários no banco de dados. Podem então fazer-se passar por estes utilizadores. Pode inclusive, se passar por um administrador de banco de dados com todos os privilégios.

O que é possível realizar com SQL Injection

O SQL Injection permite o atacante selecionar e enviar dados da base de dados. Sendo assim, pode permitir o acesso completo a todos os dados em um servidor de banco de dados.

SQL também permite alterar dados em um banco de dados e adicionar novos dados. Por exemplo, em uma aplicação financeira, um atacante poderia alterar saldos, anular transações ou transferir dinheiro para sua conta.

Você pode usar SQL para excluir registros de um banco de dados, até mesmo tabelas drop.

Mesmo se o administrador faz backups de banco de dados, exclusão de dados pode afetar a disponibilidade do aplicativo até que o banco de dados é restaurado.

Além disso, backups podem não cobrir os dados mais recentes.

Em alguns servidores de banco de dados, você pode acessar o sistema operacional usando o servidor de banco de dados. Isto pode ser intencional ou acidental. Em tal caso, um atacante poderia usar uma injeção de SQL como o vetor inicial e, em seguida, atacar a rede interna atrás de uma firewall.

Exemplos práticos de SQL Injection

Para seguir passo a passo a forma como é realizado um ataque de injecção de SQL e as consequências graves que pode ter, ver: explorar a injecção de SQL: um exemplo prático.

Autenticação

O primeiro exemplo é muito simples. Ele mostra, como um atacante pode usar uma vulnerabilidade de injeção SQL para contornar a segurança do aplicativo e autenticar como o administrador.

O seguinte script é um código executado em um servidor web. É um exemplo simples de autenticar com um nome de usuário e uma senha. O banco de dados de exemplo tem uma tabela chamada usuários com as seguintes colunas: nome de usuário e senha.

# Define variáveis de publicação
usuarioNome = request.POST ["utilizador"]
senha = request.POST ["senha"]

Agora, vamos ver a consulta realizada no backend:

# Consulta realizando concatenação simples e sem tratamento 
sql = "SELECT identidade FROM usuarios WHERE usuario= '"+ uname + "'AND senha = '" + passwd +"'”

Estes campos de entrada são vulneráveis à injecção de SQL.

Um atacante poderia usar comandos SQL na entrada de um formulário, e ao ser enviado pelo backend, passaria a ser executado pelo banco de dados. Desta forma:

senha' or 1=1;

Como resultado, o servidor de banco de dados executa a seguinte consulta:

SELECT identificacao FROM usuarios WHERE usuario='username' AND senha='password' OR 1=1'

Percebeu que o comando acima irá burlar a lógica previamente escrita?

Por causa da declaração OR 1=1, a cláusula onde retorna o primeiro id da tabela de usuários, não importa qual o nome de usuário e senha são.

O primeiro ID de usuário em um banco de dados é muitas vezes o administrador.

Desta forma, o atacante não só contorna a autenticação, mas também ganha privilégios de administrador. Eles também podem comentar o resto da declaração SQL para controlar a execução da instrução.

Como prevenir uma injecção de SQL

A única maneira segura de prevenir ataques de injeção SQL é a validação de entrada e consultas parametrizadas, incluindo declarações preparadas.

O código da aplicação nunca deve usar a entrada diretamente.

O desenvolvedor deve tratar todas as entradas, não apenas as entradas de forma web, como formulários de login. A validação sempre deve acontecer no formulário web, por JavaScript e também no backend.

Eles devem remover potenciais elementos de código maliciosos, tais como aspas simples. É também recomendado tirar a visibilidade de erros de banco de dados em seus sistemas, principalmente em ambiente de produção. Essas relatórios podem dar informações precisas sobre seu banco de dados, dando mais chances para o atacante.