asp.net - reales - tipos de inyeccion sql
¿Son los parámetros realmente suficientes para prevenir las inyecciones de Sql? (9)
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 llegué a prometerles que da inmunidad contra los ataques de inyección de SQL.
Pero estoy empezando a preguntarme si esto realmente es cierto. ¿Hay algún ataque de inyección SQL conocido que tenga éxito contra una consulta parametrizada? ¿Puede, por ejemplo, enviar una cadena que causa 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 las 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 consulta / comando.
Es posible que un proceso almacenado sea vulnerable a tipos especiales de inyección de SQL a través de desbordamiento / truncamiento, consulte: Inyección habilitada por truncamiento de datos aquí:
No, aún 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 de SQL.
''SELECT * FROM mytable WHERE colname = ?''
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 de 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á usando procedimientos almacenados o está 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 aparezcan como 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 usadas como literales de cadena en una expresión de 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, columnas, etc. En cuanto a otra sintaxis, como escribir dinámicamente expresiones SQL enteras, ese es un problema más complejo.
Parece haber cierta confusión en este hilo sobre la definición de una "consulta parametrizada".
- SQL, como un proceso almacenado que acepta parámetros.
- SQL que se llama utilizando la colección Parámetros DBMS.
Dada la definición anterior, muchos de los enlaces muestran ataques activos.
Pero la definición "normal" es la última. Dada esa definición, no sé de ningún ataque de inyección SQL que funcione. Eso no quiere decir que no haya uno, pero aún no lo he visto.
Por los comentarios, no me estoy expresando con claridad, así que aquí hay un ejemplo que con suerte será más claro:
Este enfoque está abierto a la inyección de SQL
exec dbo.MyStoredProc ''DodgyText''
Este enfoque no está abierto a la inyección de SQL
using (SqlCommand cmd = new SqlCommand("dbo.MyStoredProc", testConnection))
{
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter newParam = new SqlParameter(paramName, SqlDbType.Varchar);
newParam.Value = "DodgyText";
.....
cmd.Parameters.Add(newParam);
.....
cmd.ExecuteNonQuery();
}
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''
Solo recuerda que con los parámetros puedes almacenar fácilmente la cadena, o decir el nombre de usuario si no tienes ninguna política, "); soltar los 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).
Sus datos no son seguros si usa sql dinámico en cualquier forma o forma porque los permisos deben estar en el nivel de la tabla. Sí, ha limitado el tipo y la cantidad de ataques de inyección de esa consulta en particular, pero no está limitado el acceso que puede obtener un usuario si encuentra una forma de ingresar al sistema y usted es completamente vulnerable a que los usuarios internos accedan 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 procs 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).
Un desbordamiento de búfer no es inyección SQL.
Las consultas parametrizadas le garantizan que está seguro contra la inyección de SQL. No garantizan que no haya exploits posibles en forma de errores en su servidor SQL, pero nada lo garantizará.
cualquier parámetro sql del tipo de 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
EDIT: 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 @ p1 se selecciona de una lista desplegable, es un posible vector de ataque de inyección sql;
Si @ p1 se formula programáticamente sin la posibilidad de intervención del usuario, entonces no es un posible vector de ataque de inyección sql
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 sabor completamente diferente de ataque de una inyección SQL (el vector de ataque no sería sintaxis SQL sino binario). Como todos los parámetros aprobados se escaparon 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 columna o tabla, porque se escapan y se citan como literales de cadena.
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 serán escapadas sino que serán literales. Usar otros tipos de parámetros (como entero) es seguro.
Dicho esto, si usa la entrada de uso para establecer el valor de algo así como nivel de security_level
, entonces alguien podría hacerse a sí mismo administrador en su sistema y tener una base para todos. Pero eso es solo una validación de entrada básica, y no tiene nada que ver con la inyección de SQL.