O que é injeção de SQL?

Duplicatas possíveis:

Como funciona a injeção de SQL do quadrinho XKCD “Bobby Tables”?
https://stackoverflow.com/search?q=sql+injection

Alguém pode explicar a injeção de SQL? Como isso causa vulnerabilidades? Onde exatamente é o ponto onde o SQL é injetado?

Alguém pode explicar a injeção de SQL?

A injeção de SQL acontece quando você interpola algum conteúdo em uma string de consulta SQL e o resultado modifica a syntax de sua consulta de maneiras que você não pretendia.

Não precisa ser malicioso, pode ser um acidente. Mas a injeção acidental de SQL tem maior probabilidade de resultar em um erro do que em uma vulnerabilidade.

O conteúdo nocivo não precisa vir de um usuário, pode ser conteúdo que seu aplicativo receba de qualquer origem ou até se gere no código.

Como isso causa vulnerabilidades?

Isso pode levar a vulnerabilidades, pois os invasores podem enviar valores para um aplicativo que eles sabem que será interpolado em uma string SQL. Por ser muito inteligente, eles podem manipular o resultado de consultas, ler dados ou até mesmo alterar dados que eles não deveriam ter permissão para fazer.

Exemplo em PHP:

$password = $_POST['password']; $id = $_POST['id']; $sql = "UPDATE Accounts SET PASSWORD = '$password' WHERE account_id = $id"; 

Agora, suponha que o invasor defina os parâmetros de solicitação POST para ” password=xyzzy ” e ” id=account_id “, resultando no seguinte SQL:

 UPDATE Accounts SET PASSWORD = 'xyzzy' WHERE account_id = account_id 

Embora eu esperasse que o $id fosse um inteiro, o atacante escolheu uma string que é o nome da coluna. Claro que agora a condição é verdadeira em todas as linhas, então o atacante acaba de definir a senha para cada conta. Agora, o invasor pode fazer login na conta de qualquer pessoa, incluindo usuários privilegiados.

Onde exatamente é o ponto onde o SQL é injetado?

Não é o SQL que é injetado, é o conteúdo que é interpolado (“injetado”) em uma string SQL, resultando em um tipo diferente de consulta do que eu pretendia. Confiei no conteúdo dynamic sem verificá-lo e executei a consulta SQL resultante às cegas. É aí que o problema começa.

A injeção de SQL é uma falha no código do aplicativo, geralmente não no database ou na biblioteca ou estrutura de access ao database.

A maioria dos casos de injeção de SQL pode ser evitada usando parâmetros de consulta. Veja Como posso evitar a injeção de SQL no PHP? por exemplo.

Injeção de SQL ocorre quando o usuário de um aplicativo é capaz de afetar o significado da consulta do database. Isso geralmente ocorre quando cadeias de caracteres arbitrárias da input do usuário são concatenadas para criar o SQL que é alimentado no database. Por exemplo, vamos dizer que tivemos o seguinte código (em PHP, mas o mesmo vale para qualquer idioma), que pode ser usado para manipular um login de usuário.

 $sql = "SELECT FROM users WHERE username='".$_GET['username']."' AND password='".$_GET['password']."'"; 

O dano é feito quando o usuário digita algo como

 administrator'; -- 

… para o nome de usuário. Sem a codificação adequada, a consulta se torna:

 SELECT * FROM users WHERE username='administrator'; -- AND password='' 

O problema aqui é que o ‘no nome de usuário fecha o campo de nome de usuário, em seguida, o – inicia um comentário SQL fazendo com que o servidor de database ignore o resto da cadeia. O resultado líquido é que o usuário agora pode efetuar login como administrador sem precisar saber a senha. O SQL Inection também pode ser usado para executar consultas UPDATE, DELETE ou DROP e realmente danificar o database.

O SQL Injection pode ser evitado usando consultas parametrizadas ou aplicando as funções de escape do seu idioma / toolkit (como mysql_real_escape_string () no PHP).

Depois de entender o SQL Injection, você terá a piada por trás desse desenho animado .

A injeção de SQL é quando as coisas que supostamente são dados são tratadas como código SQL, de má vontade.

Por exemplo, se você fizesse

 mysql_query("SELECT * FROM posts WHERE postid=$postid"); 

Normalmente, você recebe o post com um determinado ID, mas assume que $postid está definido para a string 10; DROP TABLE posts -- 10; DROP TABLE posts -- ; de repente, a consulta real que você está enviando é

 mysql_query("SELECT * FROM posts WHERE postid=10; DROP TABLE posts --"); 

Isso é um grande problema, pois você perderia toda a sua tabela de posts devido a um usuário mal-intencionado – ah, querida.

A maneira mais fácil de evitar isso é usar instruções preparadas, por exemplo, por meio do PDO ou do MySQLi .

O exemplo equivalente no PDO seria então

 $statement = $db->prepare('SELECT * FROM posts WHERE postid = :postid'); $statement->bindValue(':postid', $postid); $statement->execute(); 

Isso garante que o sistema de database saiba que $ postid deve ser tratado como dados e não como código e, portanto, será tratado adequadamente.

Esta questão foi respondida muitas vezes no StackOverflow, mas é um tópico importante para todo mundo saber, então eu não vou votar para fechar esta questão.

Aqui estão links para algumas das minhas respostas anteriores sobre este tópico:

  • O que é injeção de SQL?
  • Como protejo essa function da injeção de SQL?
  • Os parâmetros são realmente suficientes para evitar injeções de Sql?
  • A injeção de SQL é um risco hoje?

Também fiz uma apresentação na Conferência MySQL deste mês e meus slides estão online:

  • Mitos e falácias de injeção de SQL

Injeção de SQL é onde um usuário mal-intencionado colocará o SQL em campos de input para tentar executar o SQL em seu servidor.

O conselho # 1 que eu aderir é usar stored procedures parametrizados em vez de construir SQL bruto no código.

Os parâmetros de Procedimento Armazenado não são executados, tornando-os seguros na maioria dos casos.

Eu encontrei este artigo para ser uma leitura extremamente boa sobre as técnicas de injeção SQL (link é para PDF): Injeção SQL avançada em aplicativos do SQL Server .

Apesar do título dizer “Avançado”, é bastante legível mesmo que você não tenha muito conhecimento sobre injeção de SQL.

Para obter informações gerais, consulte o artigo da Wikipedia sobre SQL Injection .

Em suma, os ataques de injeção de SQL podem deixá-lo vulnerável a todos os tipos de roubo e destruição de dados do database. Os detalhes exatos do que pode ser feito em seu sistema dependem dos detalhes do próprio sistema.

Toda vez que você passar a input de seus usuários para o seu database, você tem um potencial ponto de injeção. Muitas vezes, os aplicativos da Web estão faltando nesse aspecto, pois os novos programadores geralmente não entendem os riscos de manipular a input dos usuários, e os aplicativos da Web são atacados por pessoas muito inteligentes que você nunca imaginou que encontrariam seu programa.

Você vai gostar deste artigo do projeto de código; )

Resumo

  • Criptografar dados confidenciais.
  • Acesse o database usando uma conta com o mínimo de privilégios necessários.
  • Instale o database usando uma conta com o mínimo de privilégios necessários.
  • Assegure-se de que os dados sejam válidos.
  • Faça uma revisão de código para verificar a possibilidade de ataques de segunda ordem.
  • Use consultas parametrizadas.
  • Use stored procedures.
  • Revalidar dados em stored procedures.
  • Certifique-se de que as mensagens de erro não revelem nada sobre a arquitetura interna do aplicativo ou o database.

O ponto em que o SQL é injetado é qualquer ponto em que seu aplicativo aceita input do usuário.

Se isso se torna uma vulnerabilidade perigosa para seu aplicativo da web, depende se essa input é usada posteriormente como parte de uma consulta SQL sem verificar corretamente seu tipo e, se necessário, escapá-lo.

Sem o escape adequado, algum código SQL ‘injetado’ pelo usuário poderia ser executado pelo mecanismo SQL como código SQL, em vez de uma string ou valor simples.