Como é que as consultas parametrizadas ajudam contra a injecção de SQL?
em ambas as consultas 1 e 2, o texto da caixa de texto é inserido na base de dados. Qual é o significado da consulta parametrizada aqui?
1.>-------------
SqlCommand cmd = new SqlCommand("INSERT INTO dbo.Cars " +"VALUES(@TagNbr);" , conn);
cmd.Parameters.Add("@TagNbr", SqlDbType.Int);
cmd.Parameters["@TagNbr"].Value = txtTagNumber.Text;
2.>--------------
int tagnumber = txtTagNumber.Text.ToInt16(); /* EDITED */
INSERT into Cars values(tagnumber.Text); /* then is it the same? */
Também, aqui eu usaria validação de Expressão Regular para parar a inserção de caracteres ilegais.
6 answers
As consultas parametrizadas substituem adequadamente os argumentos antes de executar a consulta SQL. Ele remove completamente a possibilidade de entrada" suja " alterando o Significado de sua consulta. Isto é, se a entrada contém SQL, ela não pode se tornar parte do que é executado porque o SQL nunca é injetado na declaração resultante.
A injecção de Sql acontece quando um possível parâmetro tem sql dentro dela e as cadeias de caracteres não são tratadas como deveriam ser
Eg:
var sqlquerywithoutcommand = "select * from mytable where rowname = '" + condition+''";
E a condição é uma string que vem do usuário no pedido. Se a condição é maliciosa diga eg:
var sqlquerywithoutcommand = "select * from mytable where rowname = '" + "a' ;drop table mytable where '1=1"+"'";
Podes acabar a fazer scripts maliciosos.
Mas usando parâmetros, a entrada será limpa de todos os caracteres que possam escapar dos caracteres...
Você pode ser assegurado não importa o que vem nele não será capaz de executar programas de injeção.
Se usar o objecto de comando com parâmetros, o sql realmente executado parecerá com este
select * from mytable where rowname = 'a'';drop table mytable where 1=1'''
In essense it will be looking for a row with rowname = a'; drop table mytable where 1=1' e não executar o programa restante
Imagine uma consulta SQL dinâmica
sqlQuery='SELECT * FROM custTable WHERE User=' + Username + ' AND Pass=' + password
Então uma simples injecção de sql seria apenas para colocar o nome de Utilizador em {[4] } isto faria efectivamente a consulta sql:
sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS=' + password
Isto diz para seleccionar todos os clientes onde o seu nome de Utilizador está em branco (") ou 1=1, que é um booleano, equiparando-se ao verdadeiro. Então ele usa -- para comentar fora o resto da consulta. Então isto vai imprimir tudo mesa de clientes, ou fazer o que você quiser com ele, se entrar, ele irá entrar com os privilégios do primeiro utilizador, que muitas vezes pode ser o administrador.
Agora, as consultas parametrizadas fazem-no de forma diferente, com um código como:Parâmetros.adicionar parâmetros ("utilizador", utilizador).adicionar ("passe", senha)sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?'
Onde o nome de utilizador e a senha são variáveis que apontam para o associado utilizador e senha introduzidos
Neste momento, podes estar a pensar que isto não muda nada. de todo. De certeza que ainda podes colocar o nome de utilizador campo algo como ninguém ou 1=1'--, efetivamente fazendo a consulta:E isto parece um argumento válido. Mas, estarias errado. A forma como as consultas parametrizadas funcionam, é que o sqlQuery é enviado como um consulta, e a base de dados sabe exatamente o que esta consulta fará, e só então ele irá inserir o nome de usuário e senhas meramente como valores. Isso significa que eles não podem efetuar a consulta, porque a base de dados já sabe o que a consulta vai fazer. Então em este caso iria procurar um nome de utilizador desqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND Pass=?'
"Nobody OR 1=1'--"
e uma senha em branco, que deverá vir falso.
Com consultas parametrizadas, para além da injecção geral, terá todos os tipos de dados tratados, números (int e float), cadeias de caracteres (com aspas incorporadas), datas e horas (sem problemas de formatação ou problemas de localização quando .ToString() não é chamado com a cultura invariante e seu cliente se move para uma máquina com e formato de data inesperado).
As consultas parametrizadas permitem ao cliente passar os dados separadamente formam o texto da consulta. Onde na maioria livre de texto você faria validação + escapando. Claro que a parametrização não ajuda contra outro tipo de injeção, mas como o parâmetro é passado separadamente, eles não são usados como Consulta de texto de execução.
Uma boa analogia seria o bit de execução "recente" usado com a maioria dos modernos processadores e sistemas operacionais para proteger do excesso de buffer. Ainda permite a buffer overflow, mas evitar a execução dos dados injetados.
sqlQuery = "select * from users where username='+username+';"
Vs
sqlQuery = "select * from users where username=@username;"
Ambas as perguntas acima parecem fazer a mesma coisa.Mas na verdade não.
O primeiro usa a entrada para uma consulta, o segundo decide sobre a consulta, mas apenas substitui as entradas como é durante a execução da consulta.
Para ser mais claro, os valores dos parâmetros estão localizados em algum lugar na pilha onde a memória das variáveis é armazenada e é usada para pesquisa quando necessario.
Então, se nós fôssemos dar ' OR '1'='1
como a entrada do nome de usuário, o ex-seria dinamicamente construir uma nova consulta ou consultas como parte da string da consulta sql sqlQuery
qual é então executada.
Enquanto na mesma entrada, esta última iria procurar por ' OR '1'='
no campo username
da tabela users
com aestaticamente a pesquisa indicada no texto da pesquisasqlQuery
Só para consolidá-lo, é assim que você usa os parâmetros para fazer a consulta:
SqlCommand command = new SqlCommand(sqlQuery,yourSqlConnection);
SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "@username";
parameter.Value = "xyz";
command.Parameters.Add(parameter);