¿Cómo ayudan las consultas parametrizadas a la inyección de SQL?

En ambas consultas 1 y 2, el text del textbox se inserta en la database. ¿Cuál es el significado de la consulta parametrizada aquí?

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? */ 

Además, aquí usaría la validation de expresión regular para detener la inserción de caracteres ilegales.

Las consultas parametrizadas realizan una sustitución adecuada de los arguments antes de ejecutar la consulta SQL. Elimina por completo la posibilidad de que la input "sucia" cambie el significado de su consulta. Es decir, si la input contiene SQL, no puede formar parte de lo que se ejecuta porque el SQL nunca se inyecta en la instrucción resultante.

La inyección sql ocurre cuando un parámetro posible tiene sql dentro de él y las cadenas no se manejan como debería ser

p.ej:

 var sqlquerywithoutcommand = "select * from mytable where rowname = '" + condition+''"; 

y la condición es una cadena que proviene del usuario en la request. Si la condición es maliciosa, por ejemplo, diga:

 var sqlquerywithoutcommand = "select * from mytable where rowname = '" + "a' ;drop table mytable where '1=1"+"'"; 

podrías terminar ejecutando scripts maliciosos.

pero al usar parameters, la input se limpiará de cualquier carácter que pueda escaping de los caracteres de cadena …

puede estar seguro de que, sin importar lo que ingrese, no podrá ejecutar scripts de inyección.

utilizando el object de command con parameters el sql realmente ejecutado se vería así

 select * from mytable where rowname = 'a'';drop table mytable where 1=1''' 

en esencia, searchá una fila con rowname = a '; drop table mytable donde 1 = 1' y sin ejecutar el script restante

Imagine una consulta SQL dinámica

 sqlQuery='SELECT * FROM custTable WHERE User=' + Username + ' AND Pass=' + password 

así que una simple inyección sql sería simplemente poner el nombre de usuario como ' OR 1=1-- Esto haría efectivamente la consulta sql:

 sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS=' + password 

Esto indica que select todos los clientes cuyo nombre de usuario esté en blanco ('') o 1 = 1, que es un boolean, lo que equivale a verdadero. Luego usa – para comentar el rest de la consulta. Así que esto solo imprimirá toda la tabla de clientes, o hará lo que quiera con ella, si inicia session, iniciará session con los privilegios del primer usuario, que a menudo puede ser el administrador.

Ahora las consultas parametrizadas lo hacen de manera diferente, con un código como:

 sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?' 

parameters.add ("Usuario", nombre de usuario) parameters.add ("Pase", contraseña)

donde el nombre de usuario y la contraseña son variables que apuntan al nombre de usuario y contraseña ingresados ​​asociados

Ahora en este punto, puedes estar pensando, esto no cambia nada en absoluto. Seguramente podrías simplemente poner en el campo de nombre de usuario algo así como Nadie O 1 = 1 '-, haciendo la consulta de manera efectiva:

 sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND Pass=?' 

Y esto parecería un argumento válido. Pero, estarías equivocado.

La forma en que funcionan las consultas parametrizadas es que sqlQuery se envía como una consulta, y la database sabe exactamente lo que hará esta consulta, y solo entonces insertá el nombre de usuario y las passwords simplemente como valores. Esto significa que no pueden afectar la consulta, porque la database ya sabe lo que hará la consulta. Entonces, en este caso, searchía un nombre de usuario de "Nobody OR 1=1'--" y una contraseña en blanco, que debería aparecer como falsa.

Tomado de

Las consultas parametrizadas manejan todo: ¿por qué resolver el problema?

Con las consultas parametrizadas, además de la inyección general, obtiene todos los types de datos manejados, numbers (int y float), cadenas (con comillas incorporadas), dates y horas (no hay problemas de formatting o localización cuando .ToString () no se llama con la cultura invariante y su cliente se mueve a una máquina con un formatting de date inesperado).

Las consultas parametrizadas permiten que el cliente pase los datos por separado desde el text de la consulta. Donde más libre de text haría la validation + escapando. Por supuesto, la parametrización no ayuda contra otro tipo de inyección, pero como los parameters se pasan por separado, no se utilizan como consulta de text de ejecución.

Una buena analogía sería el bit de ejecución "reciente" utilizado con la mayoría de los procesadores modernos y el sistema operativo para proteger del desbordamiento del búfer. Todavía permite el desbordamiento del búfer pero evita la ejecución de los datos inyectados.

Es bastante comprensible por qué uno se sentiría así.

 sqlQuery = "select * from users where username='+username+';" 

vs

 sqlQuery = "select * from users where username=@username;" 

Ambas consultas anteriores parecen hacer lo mismo. Pero en realidad no lo hacen.

El primero usa la input para una consulta, este último decide sobre la consulta, pero solo sustituye las inputs tal como están durante la ejecución de la consulta.

Para ser más claros, los valores de los parameters se ubican en algún lugar de la stack donde se almacena la memory de las variables y se utilizan para search cuando sea necesario.

Entonces, si tuviéramos que dar ' OR '1'='1 como input en el nombre de usuario, el primero buildía dinámicamente nuevas consultas o consultas como parte de la cadena de consulta sql sqlQuery que luego se ejecutará.

Mientras esté en la misma input, este último searchá ' OR '1'=' en el campo de username de username de la tabla de users con la consulta estáticamente especificada en la cadena de consulta sqlQuery

Solo para consolidarlo, así es como usa parameters para realizar consultas:

 SqlCommand command = new SqlCommand(sqlQuery,yourSqlConnection); SqlParameter parameter = new SqlParameter(); parameter.ParameterName = "@username"; parameter.Value = "xyz"; command.Parameters.Add(parameter);