¿Cómo creo una consulta SQL parametrizada? ¿Por qué debería?

Resuelto Jim Counts asked hace 15 años • 6 respuestas

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

Jim Counts avatar Feb 13 '09 00:02 Jim Counts
Aceptado

El EXECejemplo 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 fuzvariable (o no, si valora la bartabla). 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.

Joel Coehoorn avatar Feb 12 '2009 17:02 Joel Coehoorn

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 Typecada 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);
Andrew Hare avatar Feb 12 '2009 17:02 Andrew Hare

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.

JAL avatar Feb 12 '2009 17:02 JAL