He estado predicando a mis colegas y aquí en SO sobre la bondad de usar parámetros en consultas SQL, especialmente en aplicaciones .NET. Incluso he ido tan lejos como para prometerles que darían inmunidad contra los ataques de inyección SQL.
Pero empiezo a preguntarme si esto realmente es cierto. ¿Existe algún ataque de inyección SQL conocido que tenga éxito contra una consulta parametrizada? ¿Puede, por ejemplo, enviar una cadena que provoque un desbordamiento del búfer en el servidor?
Por supuesto, hay otras consideraciones que hacer para garantizar que una aplicación web sea segura (como desinfectar la entrada del usuario y todo eso), pero ahora estoy pensando en inyecciones de SQL. Estoy especialmente interesado en los ataques contra MsSQL 2005 y 2008 ya que son mis bases de datos principales, pero todas las bases de datos son interesantes.
Editar: Para aclarar lo que quiero decir con parámetros y consultas parametrizadas. Al usar parámetros me refiero al uso de "variables" en lugar de construir la consulta sql en una cadena.
Entonces, en lugar de hacer esto:
SELECT * FROM Table WHERE Name = 'a name'
Nosotros hacemos esto:
SELECT * FROM Table WHERE Name = @Name
y luego establezca el valor del parámetro @Name en el objeto de consulta / comando.
fuente
Respuestas:
Los marcadores de posición son suficientes para prevenir las inyecciones. Es posible que aún esté abierto a desbordamientos de búfer, pero ese es un tipo de ataque completamente diferente de una inyección SQL (el vector de ataque no sería la sintaxis SQL sino binario). Dado que todos los parámetros pasados se escaparán correctamente, no hay forma de que un atacante pase datos que serán tratados como SQL "en vivo".
No puede usar funciones dentro de marcadores de posición, y no puede usar marcadores de posición como nombres de columnas o tablas, porque se escapan y se citan como cadenas literales.
Sin embargo, si usa parámetros como parte de una concatenación de cadenas dentro de su consulta dinámica, aún es vulnerable a la inyección, porque sus cadenas no se escaparán sino que serán literales. El uso de otros tipos de parámetros (como un número entero) es seguro.
Dicho esto, si está utilizando use input para establecer el valor de algo como
security_level
, entonces alguien podría convertirse en administradores en su sistema y tener un libre para todos. Pero eso es solo una validación de entrada básica y no tiene nada que ver con la inyección SQL.fuente
No, todavía existe el riesgo de inyección SQL cada vez que interpola datos no validados en una consulta SQL.
Los parámetros de consulta ayudan a evitar este riesgo al separar los valores literales de la sintaxis SQL.
'SELECT * FROM mytable WHERE colname = ?'
Eso está bien, pero hay otros propósitos de interpolar datos en una consulta SQL dinámica que no puede usar parámetros de consulta, porque no es un valor SQL sino un nombre de tabla, nombre de columna, expresión o alguna otra sintaxis.
'SELECT * FROM ' + @tablename + ' WHERE colname IN (' + @comma_list + ')' ' ORDER BY ' + @colname'
No importa si está utilizando procedimientos almacenados o ejecutando consultas SQL dinámicas directamente desde el código de la aplicación. El riesgo sigue ahí.
El remedio en estos casos es emplear FIEO según sea necesario:
Entrada de filtro: valide que los datos parezcan enteros legítimos, nombres de tablas, nombres de columnas, etc. antes de interpolarlos.
Salida de escape: en este caso, "salida" significa poner datos en una consulta SQL. Usamos funciones para transformar variables utilizadas como cadenas literales en una expresión SQL, de modo que las comillas y otros caracteres especiales dentro de la cadena se escapen. También deberíamos usar funciones para transformar variables que se usarían como nombres de tablas, nombres de columnas, etc. En cuanto a otras sintaxis, como escribir expresiones SQL completas de forma dinámica, ese es un problema más complejo.
fuente
Parece haber cierta confusión en este hilo sobre la definición de una "consulta parametrizada".
Dada la definición anterior, muchos de los enlaces muestran ataques en funcionamiento.
Pero la definición "normal" es la última. Dada esa definición, no conozco ningún ataque de inyección SQL que funcione. Eso no significa que no haya uno, pero aún no lo he visto.
De los comentarios, no me estoy expresando con la suficiente claridad, así que aquí hay un ejemplo que, con suerte, será más claro:
Este enfoque está abierto a la inyección SQL
Este enfoque no está abierto a la inyección de SQL
fuente
cualquier parámetro sql de tipo cadena (varchar, nvarchar, etc.) que se utiliza para construir una consulta dinámica sigue siendo vulnerable
de lo contrario, la conversión del tipo de parámetro (por ejemplo, a int, decimal, date, etc.) debería eliminar cualquier intento de inyectar sql a través del parámetro
EDITAR: un ejemplo, donde el parámetro @ p1 está destinado a ser un nombre de tabla
create procedure dbo.uspBeAfraidBeVeryAfraid ( @p1 varchar(64) ) AS SET NOCOUNT ON declare @sql varchar(512) set @sql = 'select * from ' + @p1 exec(@sql) GO
Si se selecciona @ p1 de una lista desplegable, es un vector de ataque de inyección SQL potencial;
Si @ p1 se formula programáticamente sin la capacidad del usuario para intervenir, entonces no es un vector de ataque de inyección SQL potencial
fuente
Un desbordamiento de búfer no es una inyección SQL.
Las consultas parametrizadas garantizan que está a salvo de la inyección SQL. No garantizan que no haya posibles exploits en forma de errores en su servidor SQL, pero nada lo garantizará.
fuente
Sus datos no están seguros si usa SQL dinámico de cualquier forma o forma porque los permisos deben estar a nivel de tabla. Sí, ha limitado el tipo y la cantidad de ataque de inyección de esa consulta en particular, pero no ha limitado el acceso que un usuario puede obtener si encuentra una manera de ingresar al sistema y usted es completamente vulnerable a los usuarios internos que acceden a lo que no deberían. para cometer fraude o robar información personal para vender. El SQL dinámico de cualquier tipo es una práctica peligrosa. Si utiliza procesos almacenados no dinámicos, puede establecer permisos en el nivel de proceso y ningún usuario puede hacer nada excepto lo definido por los procesos (excepto los administradores del sistema, por supuesto).
fuente
Es posible que un proceso almacenado sea vulnerable a tipos especiales de inyección SQL a través de desbordamiento / truncamiento, consulte: Inyección habilitada por truncamiento de datos aquí:
http://msdn.microsoft.com/en-us/library/ms161953.aspx
fuente
Solo recuerde que con los parámetros puede almacenar fácilmente la cadena, o decir nombre de usuario si no tiene ninguna política, "); eliminar usuarios de la tabla; -"
Esto en sí mismo no causará ningún daño, pero es mejor que sepa dónde y cómo se usa esa fecha más adelante en su aplicación (por ejemplo, almacenada en una cookie, recuperada más tarde para hacer otras cosas).
fuente
Puede ejecutar sql dinámico como ejemplo
DECLARE @SQL NVARCHAR(4000); DECLARE @ParameterDefinition NVARCHAR(4000); SELECT @ParameterDefinition = '@date varchar(10)' SET @SQL='Select CAST(@date AS DATETIME) Date' EXEC sp_executeSQL @SQL,@ParameterDefinition,@date='04/15/2011'
fuente