O que é injeção de SQL?

Usando a injeção de SQL, os invasores podem executar comandos não autorizados em um banco de dados SQL da vítima.

Objetivos de aprendizado

Após ler este artigo, você será capaz de:

  • Definir injeção de SQL
  • Explicar como funciona a injeção de SQL
  • Saber como se defender contra a injeção de SQL
  • Explorar os ataques compostos SQLI

Conteúdo relacionado


Quer saber mais?

Assine o theNET, uma recapitulação mensal feita pela Cloudflare dos insights mais populares da internet.

Consulte a política de privacidade da Cloudflare para saber como coletamos e processamos seus dados pessoais.

Copiar o link do artigo

O que é injeção de SQL (SQi)?

A injeção de Structured Query Language (SQL*) é uma técnica de injeção de código usada para modificar ou recuperar dados de bancos de dados SQL. Ao inserir instruções SQL especializadas em um campo de entrada, um invasor pode executar comandos que permitem a recuperação de dados do banco de dados, a destruição de dados sensíveis ou outros comportamentos manipuladores.

Com a execução adequada do comando SQL, o usuário não autorizado é capaz de falsificar a identidade de um usuário mais privilegiado, possibilitando que ele mesmo ou outros administradores de banco de dados, adulterem dados existentes, modifiquem transações e saldos e recuperem e/ou destruam todos os dados do servidor.

Na computação moderna, a injeção de SQL normalmente ocorre pela internet enviando consultas SQL maliciosas para um endpoint de API fornecido por um site ou serviço (mais informações sobre isso adiante). Em sua forma mais severa, a injeção de SQL pode permitir que um invasor obtenha acesso root a uma máquina, dando a ele controle total.

*SQL é uma linguagem de programação usada para manter a maioria dos bancos de dados.

Como funciona um ataque de injeção de SQL?

Imagine um tribunal em que um homem chamado Bob está sendo julgado e está prestes a comparecer perante um juiz. Ao preencher a papelada antes do julgamento, Bob escreve seu nome como “Bob está livre”. Quando o juiz chega ao seu caso e lê em voz alta “Agora, chamo Bob está livre”, o oficial de justiça deixa Bob ir porque o juiz disse isso.

Embora existam variações ligeiramente diferentes de SQLi, a vulnerabilidade principal é essencialmente a mesma: um campo de consulta SQL que deveria ser reservado para um tipo específico de dados, como um número, recebe informações inesperadas, como um comando. O comando, quando executado, escapa além dos limites pretendidos, permitindo um comportamento potencialmente nefasto. Um campo de consulta geralmente é preenchido a partir de dados inseridos em um formulário em uma página web.

Vejamos uma comparação simples entre instruções SQL normais e maliciosas:

Consulta SQL normal:

Nesta consulta SQL normal, a string studentId é passada para uma instrução SQL. O objetivo é procurar na lista de alunos um aluno que corresponda ao studentId inserido. Uma vez encontrado, o registro desse aluno será devolvido. Simplificando, o comando diz “vá encontrar este usuário e me forneça seus dados”.

O código pode ser algo assim:

studentId = getRequestString("studentId");
lookupStudent = "SELECT * FROM students WHERE studentId = " + studentId
   

Se um estudante digitar uma ID de estudante 117 em um formulário de página web com a instrução "Digite seu número de ID de estudante".

campo do formulário normal

a consulta SQL resultante será semelhante a:

SELECT * FROM students WHERE studentId = 117;

Este comando retornará o registro para o aluno específico com um studentId, que é o que o desenvolvedor que escreveu a API espera que aconteça.

Consulta de injeção de SQL:

Neste exemplo, um invasor insere um comando SQL ou lógica condicional no campo de entrada, ele insere um número de identificação do aluno de:

campo de formulário de exemplo de injeção de SQL

Onde normalmente a consulta pesquisaria a tabela do banco de dados pela ID correspondente, agora ela procura uma ID ou testes para ver se 1 é igual a 1. Como você poderia esperar, a afirmação é sempre verdadeira para todos os alunos na coluna e, como como resultado, o banco de dados retornará todos os dados da tabela de alunos de volta ao invasor que fizer a consulta.

SELECT * FROM students WHERE studentId = 117 OR 1=1;
Infográfico de injeção de SQL

A SQLi funciona visando uma interface de programação de aplicativos ou API vulnerável. Uma API neste caso é a interface de software por meio da qual um servidor recebe e responde às solicitações.

Existem ferramentas comumente usadas que permitem que um agente malicioso pesquise automaticamente em um site procurando formulários e tente inserir várias consultas de SQL que podem gerar uma resposta que os desenvolvedores de software do site não pretendiam para explorar o banco de dados.

As injeções de SQL são fáceis de implementar e, curiosamente, também bastante fáceis de evitar, dadas as práticas de desenvolvimento adequadas. A realidade é mais obscura, pois prazos apertados, desenvolvedores inexperientes e código legado geralmente resultam em práticas de segurança e qualidade de código variáveis. Um único campo vulnerável em qualquer formulário ou endpoint de API, em um site que tenha acesso a um banco de dados, pode ser suficiente para expor uma vulnerabilidade.

Como um ataque de injeção de SQL pode ser evitado?

Existem vários métodos para reduzir o risco de violação de dados devido à injeção de SQL. Várias estratégias devem ser utilizadas, conforme as práticas recomendadas. Vamos explorar algumas das implementações mais comuns:

  • Usar instruções preparadas (com consultas parametrizadas) - Este método de sanitizar entradas de banco de dados envolve forçar os desenvolvedores a primeiro definir todo o código SQL e, em seguida, passar apenas parâmetros para a consulta SQL; os dados inseridos recebem explicitamente um escopo limitado que não pode ser expandido. Isso permite que o banco de dados faça a distinção entre os dados que estão sendo inseridos e o código que está sendo executado, independentemente do tipo de dados fornecidos no campo de entrada. Algumas bibliotecas de mapeamento de objeto relacional (ORM) são comumente utilizadas para essa finalidade, pois algumas versões higienizam as entradas do banco de dados automaticamente.
  • "Escapar" todas as entradas fornecidas pelo usuário - Ao escrever a SQL, caracteres ou palavras específicos têm um significado particular. Por exemplo, o caractere "*" significa “qualquer” e a palavra “OR” é uma condicional. Para contornar usuários que inserem esses caracteres acidentalmente ou maliciosamente em uma solicitação de API para o banco de dados, a entrada fornecida pelo usuário pode ser "escapada". "Escapar" um caractere é a maneira de dizer ao banco de dados para não analisá-lo como um comando ou condicional, mas sim tratá-lo como entrada literal.
  • Usar procedimentos armazenados - Embora não seja uma estratégia de segurança robusta por si só, os procedimentos armazenados podem ajudar a limitar o risco associado à injeção de SQL. Ao limitar adequadamente as permissões da conta de banco de dados executando consultas de SQL, mesmo o código de aplicativo não robusto que é vulnerável à injeção de SQL não terá as permissões necessárias para manipular tabelas de banco de dados não relacionadas. Os procedimentos armazenados também podem verificar o tipo de parâmetros de entrada, evitando que sejam inseridos dados que violem o tipo que o campo foi projetado para receber. Nos casos em que as consultas estáticas são insuficientes, os procedimentos armazenados normalmente devem ser evitados.
  • Reforçar o menor privilégio - Como regra geral, em todos os casos em que um site precisa usar SQL dinâmica, é importante reduzir a exposição à injeção de SQL limitando as permissões ao escopo mais restrito necessário para executar a consulta relevante . Em sua forma mais óbvia, isso significa que uma conta administrativa não deve, em hipótese nenhuma, executar comandos de SQL como resultado de uma chamada de API de uma solicitação não autorizada. Embora os procedimentos armazenados sejam melhor utilizados para consultas estáticas, a aplicação do menor privilégio pode ajudar a reduzir os riscos de consultas SQL dinâmicas.

O que é um ataque de injeção SQL combinado?

Para contornar as medidas de segurança, invasores inteligentes às vezes implementam ataques multivetoriais contra um site alvo. Embora um único ataque possa ser mitigado, ele também pode se tornar o foco de atenção dos administradores de banco de dados e das equipes de segurança da informação. Ataques DDoS, sequestro de DNS e outros métodos de interrupção às vezes são usados como uma distração para implementar ataques abrangentes de injeção de SQL. Como resultado, uma estratégia abrangente de mitigação de ameaças fornece a mais ampla gama de proteção. O firewall de aplicativos web,a mitigação de DDoS e a segurança de DNS da Cloudflare abrangem os principais elementos de uma estratégia de segurança holística.