Eu sei que o PreparedStatements evita / impede a injeção de SQL. Como isso acontece? A consulta final do formulário criada usando PreparedStatements será uma sequência ou não?
Eu sei que o PreparedStatements evita / impede a injeção de SQL. Como isso acontece? A consulta final do formulário criada usando PreparedStatements será uma sequência ou não?
Respostas:
O problema com a injeção SQL é que uma entrada do usuário é usada como parte da instrução SQL. Usando instruções preparadas, você pode forçar a entrada do usuário a ser tratada como o conteúdo de um parâmetro (e não como parte do comando SQL).
Mas se você não usar a entrada do usuário como parâmetro para sua instrução preparada, mas construir seu comando SQL juntando cadeias, ainda estará vulnerável às injeções de SQL, mesmo ao usar instruções preparadas.
Considere duas maneiras de fazer a mesma coisa:
PreparedStatement stmt = conn.createStatement("INSERT INTO students VALUES('" + user + "')");
stmt.execute();
Ou
PreparedStatement stmt = conn.prepareStatement("INSERT INTO student VALUES(?)");
stmt.setString(1, user);
stmt.execute();
Se "usuário" veio da entrada do usuário e a entrada do usuário foi
Robert'); DROP TABLE students; --
Então, em primeira instância, você seria processado. No segundo, você estaria seguro e Little Bobby Tables seria registrado para sua escola.
Para entender como o PreparedStatement impede a injeção de SQL, precisamos entender as fases da execução da Consulta ao SQL.
1. Fase de compilação. 2. Fase de execução.
Sempre que o mecanismo do SQL Server recebe uma consulta, ele precisa passar pelas fases abaixo,
Fase de análise e normalização: nesta fase, a consulta é verificada quanto à sintaxe e semântica. Ele verifica se as tabelas e colunas de referência usadas na consulta existem ou não. Ele também tem muitas outras tarefas, mas não vamos detalhar.
Fase de compilação: nesta fase, as palavras-chave usadas em consultas como select, from, where etc são convertidas em formato compreensível por máquina. Essa é a fase em que a consulta é interpretada e a ação correspondente a ser tomada é decidida. Ele também tem muitas outras tarefas, mas não vamos detalhar.
Plano de otimização de consulta: nesta fase, a Árvore de decisão é criada para encontrar as maneiras pelas quais a consulta pode ser executada. Ele descobre o número de maneiras pelas quais a consulta pode ser executada e o custo associado a cada maneira de executar a Consulta. Ele escolhe o melhor plano para executar uma consulta.
Cache: o melhor plano selecionado no plano de otimização de consulta é armazenado em cache, para que, sempre que a próxima consulta entre na mesma consulta, ela não precise passar pela Fase 1, Fase 2 e Fase 3 novamente. Quando a consulta da próxima vez chegar, ela será verificada diretamente no cache e retirada de lá para ser executada.
Fase de execução:
nesta fase, a consulta fornecida é executada e os dados são retornados ao usuário como ResultSet
objeto.
PreparedStatements não são consultas SQL completas e contém espaços reservados, que em tempo de execução são substituídos por dados reais fornecidos pelo usuário.
Sempre que qualquer PreparedStatment que contém espaços reservados é passado para o mecanismo do SQL Server, ele passa pelas fases abaixo
UPDATE usuário definido nome de usuário =? e senha =? ONDE id =?
A consulta acima será analisada, compilada com espaços reservados como tratamento especial, otimizada e será armazenada em cache. A consulta nesse estágio já está compilada e convertida em formato compreensível por máquina. Portanto, podemos dizer que a consulta armazenada no cache é pré-compilada e apenas os espaços reservados precisam ser substituídos pelos dados fornecidos pelo usuário.
Agora, no tempo de execução, quando os dados fornecidos pelo usuário são recebidos, a Consulta Pré-Compilada é selecionada no Cache e os espaços reservados são substituídos pelos dados fornecidos pelo usuário.
(Lembre-se, depois que os marcadores de posição são substituídos pelos dados do usuário, a consulta final não é compilada / interpretada novamente e o mecanismo do SQL Server trata os dados do usuário como dados puros e não como um SQL que precisa ser analisado ou compilado novamente; essa é a beleza do PreparedStatement. )
Se a consulta não precisar passar pela fase de compilação novamente, todos os dados substituídos nos espaços reservados serão tratados como dados puros e não terão significado para o mecanismo do SQL Server e executarão a consulta diretamente.
Nota: É a fase de compilação após a fase de análise que compreende / interpreta a estrutura da consulta e fornece um comportamento significativo a ela. No caso de PreparedStatement, a consulta é compilada apenas uma vez e a consulta compilada em cache é selecionada o tempo todo para substituir os dados do usuário e executar.
Devido ao recurso de compilação único do PreparedStatement, ele está livre de ataques de injeção de SQL.
Você pode obter explicações detalhadas com o exemplo aqui: https://javabypatel.blogspot.com/2015/09/how-prepared-statement-in-java-prevents-sql-injection.html
O SQL usado em um PreparedStatement é pré-compilado no driver. A partir desse momento, os parâmetros são enviados ao driver como valores literais e não como partes executáveis do SQL; portanto, nenhum SQL pode ser injetado usando um parâmetro. Outro efeito colateral benéfico de PreparedStatements (pré-compilação + envio apenas de parâmetros) é um desempenho aprimorado ao executar a instrução várias vezes, mesmo com valores diferentes para os parâmetros (supondo que o driver suporte PreparedStatements), pois o driver não precisa executar a análise e compilação do SQL cada tempo em que os parâmetros mudam.
Eu acho que vai ser uma corda. Mas os parâmetros de entrada serão enviados ao banco de dados e as conversões / conversão apropriadas serão aplicadas antes da criação de uma instrução SQL real.
Para dar um exemplo, ele pode tentar e ver se o CAST / Conversion funciona.
Se funcionar, poderá criar uma declaração final.
SELECT * From MyTable WHERE param = CAST('10; DROP TABLE Other' AS varchar(30))
Tente um exemplo com uma instrução SQL aceitando um parâmetro numérico.
Agora, tente passar uma variável de string (com conteúdo numérico aceitável como parâmetro numérico). Isso gera algum erro?
Agora, tente passar uma variável de sequência (com conteúdo que não é aceitável como parâmetro numérico). Veja o que acontece?
A declaração preparada é mais segura. Ele converterá um parâmetro para o tipo especificado.
Por exemplo stmt.setString(1, user);
, converterá o user
parâmetro em uma String.
Suponha que o parâmetro contenha uma string SQL contendo um comando executável : o uso de uma instrução preparada não permitirá isso.
Ele adiciona metacaractere (também conhecido como conversão automática) a isso.
Isso torna mais seguro.
Injeção de SQL: quando o usuário tem a chance de inserir algo que possa fazer parte da instrução sql
Por exemplo:
Consulta de seqüência de caracteres = "INSERIR EM VALORES DOS ALUNOS ('” + usuário + "')"
quando o usuário digita "Robert '); Alunos da DROP TABLE; - ”como entrada, causa injeção SQL
Como a declaração preparada impede isso?
Consulta de seqüência de caracteres = "INSERIR EM VALORES DOS ALUNOS ('” + ": nome" + "')"
parameters.addValue ("nome", usuário);
=> quando o usuário inserir novamente “Robert '); Alunos da DROP TABLE; - “, a string de entrada é pré-compilada no driver como valores literais e acho que pode ser convertida como:
CAST ('Robert'); Alunos da DROP TABLE; - «AS varchar (30))
Portanto, no final, a string será literalmente inserida como o nome da tabela.
http://blog.linguiming.com/index.php/2018/01/10/why-prepared-statement-avoids-sql-injection/
CAST(‘Robert’);
de CAST(‘Robert’); DROP TABLE students; –‘ AS varchar(30))
iria quebrar, então ele iria continuar a cair da mesa, se fosse esse o caso. Ele interrompe a injeção, então acredito que o exemplo não está completo o suficiente para explicar o cenário.
Declaração preparada:
1) A pré-compilação e o armazenamento em cache do lado do banco de dados da instrução SQL levam à execução geral mais rápida e à capacidade de reutilizar a mesma instrução SQL em lotes.
2) Prevenção automática de ataques de injeção de SQL por escape interno de aspas e outros caracteres especiais. Observe que isso requer que você use qualquer um dos métodos setedxx PreparedStatement () para definir o valor.
Conforme explicado neste post , o PreparedStatement
sozinho não ajuda se você ainda estiver concatenando Strings.
Por exemplo, um invasor não autorizado ainda pode fazer o seguinte:
Não apenas o SQL, mas também o JPQL ou o HQL podem ser comprometidos se você não estiver usando parâmetros de ligação.
Bottom line, você nunca deve usar concatenação de seqüência de caracteres ao criar instruções SQL. Use uma API dedicada para esse fim:
Nas declarações preparadas, o usuário é forçado a inserir dados como parâmetros. Se o usuário digitar algumas instruções vulneráveis como DROP TABLE ou SELECT * FROM USERS, os dados não serão afetados, pois serão considerados parâmetros da instrução SQL