A ideia é muito simples - a consulta e os dados são enviados ao servidor de banco de dados separadamente .
Isso é tudo.
A raiz do problema de injeção de SQL está na mistura do código e dos dados.
De fato, nossa consulta SQL é um programa legítimo . E estamos criando esse programa dinamicamente, adicionando alguns dados rapidamente. Assim, os dados podem interferir no código do programa e até alterá-lo, como todo exemplo de injeção de SQL mostra (todos os exemplos em PHP / Mysql):
$expected_data = 1;
$query = "SELECT * FROM users where id=$expected_data";
produzirá uma consulta regular
SELECT * FROM users where id=1
enquanto esse código
$spoiled_data = "1; DROP TABLE users;"
$query = "SELECT * FROM users where id=$spoiled_data";
produzirá uma sequência maliciosa
SELECT * FROM users where id=1; DROP TABLE users;
Funciona porque estamos adicionando os dados diretamente ao corpo do programa e ele se torna parte do programa, para que os dados possam alterar o programa e, dependendo dos dados transmitidos, teremos uma saída regular ou uma tabela users
excluída.
Embora, no caso de declarações preparadas, não alteremos nosso programa, ele permanece intacto.
Esse é o ponto.
Estamos enviando um programa para o servidor primeiro
$db->prepare("SELECT * FROM users where id=?");
onde os dados são substituídos por alguma variável chamada parâmetro ou espaço reservado.
Observe que exatamente a mesma consulta é enviada ao servidor, sem dados! E então estamos enviando os dados com a segunda solicitação, essencialmente separados da própria consulta:
$db->execute($data);
portanto, não pode alterar nosso programa e causar algum dano.
Muito simples - não é?
A única coisa que devo acrescentar é que sempre omitido em todos os manuais:
As instruções preparadas podem proteger apenas literais de dados , mas não podem ser usadas com nenhuma outra parte da consulta.
Assim, uma vez que precisamos adicionar, digamos, um identificador dinâmico - um nome de campo, por exemplo - as instruções preparadas não podem nos ajudar. Eu expliquei o assunto recentemente , então não vou me repetir.
$spoiled_data = "1; DROP TABLE users;"
->$query = "SELECT * FROM users where id=$spoiled_data";
, comparado com:$db->prepare("SELECT * FROM users where id=?");
->$data = "1; DROP TABLE users;"
->$db->execute($data);
. Eles não farão a mesma coisa?Aqui está o SQL para configurar um exemplo:
A classe Inject é vulnerável à injeção de SQL. A consulta é colada dinamicamente junto com a entrada do usuário. O objetivo da consulta era mostrar informações sobre Bob. Salário ou bônus, com base nas informações do usuário. Mas o usuário mal-intencionado manipula a entrada que corrompe a consulta, aplicando o equivalente a uma cláusula 'ou true' na cláusula where, para que tudo seja retornado, incluindo as informações sobre Aaron que deveriam estar ocultas.
Executando isso, o primeiro caso é com o uso normal e o segundo com a injeção maliciosa:
Você não deve construir suas instruções SQL com concatenação de string da entrada do usuário. Ele não é apenas vulnerável à injeção, mas também tem implicações de armazenamento em cache no servidor (a instrução é alterada, é menos provável obter um cache de instrução SQL, enquanto o exemplo de ligação está sempre executando a mesma instrução).
Aqui está um exemplo de ligação para evitar esse tipo de injeção:
Executar isso com a mesma entrada do exemplo anterior mostra que o código malicioso não funciona porque não há paymentType correspondente a essa sequência:
fonte
PREPARE
cria uma instrução nomeada fixa que já está analisada (ou seja, a instrução não será mais alterada, independentemente da entrada), enquantoEXECUTE
executará a instrução nomeada vinculando os parâmetros. ComoPREPARE
só tem duração de sessão, parece realmente que foi feito por motivos de desempenho, não para impedir a injeção via scripts psql. Para acesso ao psql, poderia conceder permissões aos procedimentos armazenados e vincular os parâmetros nos procs.Basicamente, com instruções preparadas, os dados provenientes de um hacker em potencial são tratados como dados - e não há como eles serem misturados com o aplicativo SQL e / ou interpretados como SQL (o que pode acontecer quando os dados passados são colocados diretamente no seu aplicativo). aplicação SQL).
Isso ocorre porque as instruções preparadas "preparam" a consulta SQL primeiro para encontrar um plano de consulta eficiente e enviam os valores reais que presumivelmente vêm de um formulário posteriormente - naquele momento, a consulta é realmente executada.
Mais informações excelentes aqui:
Instruções preparadas e injeção de SQL
fonte
Li as respostas e ainda senti a necessidade de enfatizar o ponto principal que ilumina a essência das Declarações Preparadas. Considere duas maneiras de consultar o banco de dados em que a entrada do usuário está envolvida:
Abordagem ingênua
Um concatena a entrada do usuário com alguma string SQL parcial para gerar uma instrução SQL. Nesse caso, o usuário pode incorporar comandos SQL maliciosos, que serão enviados ao banco de dados para execução.
Por exemplo, a entrada maliciosa do usuário pode levar a
SQLString
ser igual a"SELECT * FROM CUSTOMERS WHERE NAME='James';DROP TABLE CUSTOMERS;'
Devido ao usuário mal-intencionado,
SQLString
contém 2 instruções, sendo que a segunda ("DROP TABLE CUSTOMERS"
) causará danos.Declarações Preparadas
Nesse caso, devido à separação da consulta e dos dados, a entrada do usuário nunca é tratada como uma instrução SQL e , portanto, nunca é executada . É por esse motivo que qualquer código SQL malicioso injetado não causaria danos. Portanto,
"DROP TABLE CUSTOMERS"
isso nunca seria executado no caso acima.Em poucas palavras, com instruções preparadas, códigos maliciosos introduzidos pela entrada do usuário não serão executados!
fonte
Quando você cria e envia uma instrução preparada para o DBMS, ela é armazenada como a consulta SQL para execução.
Posteriormente, você vincula seus dados à consulta para que o DBMS os utilize como parâmetros de consulta para execução (parametrização). O DBMS não usa os dados que você vincula como um complemento para a consulta SQL já compilada; são simplesmente os dados.
Isso significa que é fundamentalmente impossível executar a injeção de SQL usando instruções preparadas. A própria natureza das declarações preparadas e seu relacionamento com o DBMS evita isso.
fonte
No SQL Server , o uso de uma instrução preparada é definitivamente à prova de injeção, porque os parâmetros de entrada não formam a consulta. Isso significa que a consulta executada não é uma consulta dinâmica. Exemplo de uma instrução vulnerável de injeção SQL.
Agora, se o valor na variável inoutusername é algo como 'ou 1 = 1 -, essa consulta agora se torna:
E o restante é comentado depois
--
, para que nunca seja executado e ignorado como usando o exemplo de instrução preparada como abaixo.Portanto, na verdade, você não pode enviar outro parâmetro, evitando a injeção de SQL ...
fonte
A frase chave é
need not be correctly escaped
. Isso significa que você não precisa se preocupar com pessoas tentando colocar traços, apóstrofos, citações, etc ...Tudo é tratado para você.
fonte
Vamos supor que você tenha isso em um Servlet, certo. Se uma pessoa malévola passou um valor ruim para 'filtro', você pode invadir seu banco de dados.
fonte
Causa Raiz # 1 - O Problema do Delimitador
A injeção de sql é possível porque usamos aspas para delimitar seqüências de caracteres e também para fazer parte delas, tornando impossível às vezes interpretá-las. Se tivéssemos delimitadores que não pudessem ser usados em dados de string, a injeção de sql nunca teria acontecido. Resolver o problema do delimitador elimina o problema de injeção de sql. As consultas de estrutura fazem isso.
Causa raiz # 2 - A natureza humana, as pessoas são astutas e algumas astuciosas são maliciosas e todas as pessoas cometem erros
A outra causa raiz da injeção de sql é a natureza humana. Pessoas, incluindo programadores, cometem erros. Quando você comete um erro em uma consulta estruturada, isso não torna seu sistema vulnerável à injeção de sql. Se você não estiver usando consultas estruturadas, erros podem gerar vulnerabilidade de injeção de sql.
Como as consultas estruturadas resolvem as causas principais da injeção de SQL
Consultas estruturadas resolvem o problema do delimitador, colocando comandos sql em uma instrução e colocando os dados em uma instrução de programação separada. As instruções de programação criam a separação necessária.
Consultas estruturadas ajudam a impedir que erros humanos criem falhas críticas de segurança. Com relação aos humanos cometendo erros, a injeção de sql não pode acontecer quando as consultas de estrutura são usadas. Existem maneiras de impedir a injeção de sql que não envolvem consultas estruturadas, mas o erro humano normal nessas abordagens geralmente leva a pelo menos alguma exposição à injeção de sql. As consultas estruturadas são protegidas contra falhas da injeção de sql. Você pode cometer todos os erros do mundo, quase, com consultas estruturadas, iguais a qualquer outra programação, mas nenhuma delas pode ser transformada em um sistema assumido pela injeção de sql. É por isso que as pessoas gostam de dizer que este é o caminho certo para evitar a injeção de sql.
Então, aí está, as causas da injeção de sql e as consultas estruturadas da natureza que as tornam impossíveis quando usadas.
fonte