¿Cómo creo una consulta SQL parametrizada? ¿Por qué debería?
He oído que "todo el mundo" utiliza consultas SQL parametrizadas para protegerse contra ataques de inyección SQL sin tener que validar cada entrada del usuario.
¿Cómo haces esto? ¿Obtiene esto automáticamente cuando utiliza procedimientos almacenados?
Entonces, según tengo entendido, esto no está parametrizado:
cmdText = String.Format("SELECT foo FROM bar WHERE baz = '{0}'", fuz)
¿Estaría esto parametrizado?
cmdText = String.Format("EXEC foo_from_baz '{0}'", fuz)
¿O necesito hacer algo más extenso como esto para protegerme de la inyección SQL?
With command
.Parameters.Count = 1
.Parameters.Item(0).ParameterName = "@baz"
.Parameters.Item(0).Value = fuz
End With
¿Existen otras ventajas al utilizar consultas parametrizadas además de las consideraciones de seguridad?
Actualización: este gran artículo fue vinculado en una de las referencias de preguntas de Grotok. http://www.sommarskog.se/dynamic_sql.html
El EXEC
ejemplo de la pregunta NO estaría parametrizado. Necesita consultas parametrizadas (declaraciones preparadas en algunos círculos) para evitar que entradas como esta causen daños:
';barra DROP TABLE;--
Intente poner eso en su fuz
variable (o no, si valora la bar
tabla). También son posibles consultas más sutiles y perjudiciales.
A continuación se muestra un ejemplo de cómo se configuran los parámetros con Sql Server:
Public Function GetBarFooByBaz(ByVal Baz As String) As String
Dim sql As String = "SELECT foo FROM bar WHERE baz= @Baz"
Using cn As New SqlConnection("Your connection string here"), _
cmd As New SqlCommand(sql, cn)
cmd.Parameters.Add("@Baz", SqlDbType.VarChar, 50).Value = Baz
Return cmd.ExecuteScalar().ToString()
End Using
End Function
A los procedimientos almacenados a veces se les atribuye el mérito de prevenir la inyección de SQL. Sin embargo, la mayoría de las veces todavía tienes que llamarlos usando parámetros de consulta o no ayudan. Si utiliza procedimientos almacenados exclusivamente , puede desactivar los permisos para SELECCIONAR, ACTUALIZAR, ALTERAR, CREAR, ELIMINAR, etc. (casi todo menos EXEC) para la cuenta de usuario de la aplicación y obtener cierta protección de esa manera.
Desea continuar con su último ejemplo, ya que este es el único que está verdaderamente parametrizado. Además de los problemas de seguridad (que son mucho más frecuentes de lo que podría pensar), es mejor dejar que ADO.NET se encargue de la parametrización, ya que no puede estar seguro de si el valor que está pasando requiere comillas simples o no sin inspeccionar Type
cada parámetro. .
[Editar] Aquí hay un ejemplo:
SqlCommand command = new SqlCommand(
"select foo from bar where baz = @baz",
yourSqlConnection
);
SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "@baz";
parameter.Value = "xyz";
command.Parameters.Add(parameter);
La mayoría de la gente haría esto a través de una biblioteca de lenguajes de programación del lado del servidor, como PHP PDO o Perl DBI.
Por ejemplo, en DOP:
$dbh=pdo_connect(); //you need a connection function, returns a pdo db connection
$sql='insert into squip values(null,?,?)';
$statement=$dbh->prepare($sql);
$data=array('my user supplied data','more stuff');
$statement->execute($data);
if($statement->rowCount()==1){/*it worked*/}
Esto se encarga de escapar de sus datos para la inserción en la base de datos.
Una ventaja es que puede repetir un inserto muchas veces con una declaración preparada, obteniendo una ventaja de velocidad.
Por ejemplo, en la consulta anterior, podría preparar la declaración una vez y luego crear la matriz de datos a partir de un conjunto de datos y repetir ->ejecutar tantas veces como sea necesario.