2012-06-20 10 views
7

Sé acerca de los usos de los parámetros en oraciones sql, pero solo por curiosidad es seguro usar la función Format para evitar las inyecciones sql en lugar de utilizar parámetros.¿Función de formato frente a parámetros en los escenarios de inyección sql?

como esta muestra

sCustomer : string 
begin 
AdoSql.CommandText:=Format('Select SUM(value) result from invoices where customer=%s',[QuotedStr(sCustomer)]); 
end; 
+1

Creo que el título debería haber sido 'Función QuotedStr vs Parámetros en los escenarios de inyección de sql?', Pero al cambiarlo, se desglosan algunas respuestas aquí. el * problema * aquí es sobre 'QuotedStr' y no' Format'. – kobik

Respuesta

11

Eso sería probablemente ser seguras contra la inyección de SQL, asumiendo QuotedStr funciona como se espera y no hay casos extremos que pueden romperlo. (Lo cual de ninguna manera está garantizado. Como señaló Linas en un comentario, MySql le permite usar \' para escapar las comillas. Otros DBMS probablemente tengan capacidades similares. Un atacante con suficiente conocimiento teórico del sistema podría explotarlos).

Sin embargo, incluso si QuotedStr fuera lo suficientemente bueno, es mejor usar parámetros por un motivo diferente: el rendimiento. Cuando separa los parámetros de su consulta, puede terminar enviando exactamente el mismo código de consulta varias veces con diferentes parámetros. Si lo hace, la base de datos puede almacenar en caché gran parte del trabajo que realiza al calcular la consulta, por lo que su acceso a la base de datos se vuelve más rápido. Eso no funciona (o al menos no tan bien) cuando se mezclan los parámetros en el código de consulta en sí.

+6

+1 para el comentario sobre "caché", muchos Servidores SQL pueden reutilizar el plan de ejecución de las sentencias sql. – RRUZ

+3

Eso probablemente sería inseguro en MySQL porque MySQL permite \ 'escapar de una cita para que QuotedStr no ayude aquí. – Linas

+0

@Linas: Buen punto. Editado para tener esto en cuenta. –

5

Cada vez que crea una cadena SQL concatenando cadenas, existe la posibilidad de un ataque de inyección, sin importar cuán seguro piense que es el acceso a esas cadenas. Por lo que usted sabe, alguien podría ejecutar su aplicación dentro de un depurador, poner un punto de interrupción en el resultado de QuotedStr() y modificar su contenido antes de permitir que Format() lo vea.

El uso de parámetros SQL reales es la forma más segura de hacerlo. No solo evita las inyecciones, sino que también permite que el motor de SQL decida la mejor forma de formatear los parámetros según sus propias necesidades, de modo que no tenga que preocuparse por formatear los valores en su propio código, sino que funciona bien con tipos de letra fuerte. idiomas (como Delphi). Sin mencionar los beneficios de rendimiento de poder preparar la declaración de SQL en el lado del servidor antes de ejecutarla en el código, incluso varias veces, reduciendo drásticamente el tráfico entre el cliente y el servidor y aumentando el rendimiento general.

var 
    sCustomer : string 
begin 
    AdoSql.CommandText := 'Select SUM(value) result from invoices where customer=:Customer'; 
    AdoSql.Prepared := True; 
    ... 
    AdoSql.Parameters['Customer'].Value := sCustomer; 
    AdoSql1.ExecSQL; 
    ... 
    AdoSql.Parameters['Customer'].Value := sCustomer; 
    AdoSql1.ExecSQL; 
    ... 
    AdoSql.Prepared := False; 
end; 
+3

Ese primer párrafo es un poco tonto. La inyección de SQL se trata básicamente de obtener acceso no autorizado a la base de datos. Pero si alguien tiene acceso de nivel de depuración a su aplicación, no * necesita * un ataque de inyección SQL para obtener acceso a la base de datos; se puede suponer que ya tienen acceso a él, al mismo nivel de privilegio que la aplicación en sí. –

+1

No si la aplicación utiliza una conexión encriptada a la base de datos, o si el atacante no puede, o no quiere, determinar qué tipo de base de datos se está utilizando o cómo acceder directamente a ella. Deje que la aplicación haga todo el trabajo, simplemente cambie el SQL que se ejecuta. –

+2

En este escenario, el uso de parámetros también sería inseguro ya que el usuario podría cambiar los valores de los parámetros, algo que a veces hago cuando depuro mis propias aplicaciones. –

5

No, Format no ofrece seguridad desde la inyección SQL. No es diferente de la concatenación de cadenas ordinaria en ese sentido.

La parte del código en la pregunta que hace algo en contra de la inyección SQL es la llamada al QuotedStr, que puede usar con o sin Format. Sin embargo, no es tan confiable como las consultas con parámetros reales.

En este contexto, la única ventaja de Format es que toda la plantilla de cadena está en un solo lugar, por lo que es menos probable que obtenga espaciado y puntuación incorrectos de lo que sería si tuviera que construir la cadena con operaciones sucesivas + , donde los apóstrofos de SQL podrían perderse entre los apóstrofos de Delphi.

Cuestiones relacionadas