SQL SERVER CONSULTAS DINÁMICAS PARAMETRIZADAS EN PROCEDIMIENTOS ALMACENADOS

No soy amigo de usar sentencias SQL dinámicas en procedimientos almacenados pero debo admitir que algunas veces debemos hacer uso de ellas para dar solución a problemas específicos. Uno de los enormes riesgos que implica usar consultas dinámicas en SQL server es la exposición a posibles ataques de inyección de código sql en nuestros procedimientos.

Imaginemos por un instante que tenemos el siguiente procedimiento almacenado que nos el total de tarjetas de crédito de un determinado tipo:

create procedure Sp_MAL_Tarjetas(@tipo as varchar(100)) as
declare @sql varchar(500)
set @sql = select count(*)
from [Sales].[CreditCard] where CardType = + @tipo +
exec(@sql)

El grave problema de este procedimiento almacenado es que permite concatenar cadenas sin validar que el contenido en ellas esté libre de código SQL, permitiendo con ello una inyección de código de la siguiente forma:

declare
@prueba varchar(100)

set @prueba = SuperiorCard select *
from [Sales].[CreditCard] where CardType <>

Execute Sp_MAL_Tarjetas @prueba

Al ejecutar el procedimiento almacenado obtendremos el siguiente resultado:

SQL_Server_Dynamic_SQL

Como puede notarse, la gravedad de hacer una consulta dinámica sin validar el contenido de los parámetros es enorme. Para solucionar esto podría hacerse uso de un parser que eliminara las sentencias sql contenidas en los parámetros pero SQL Server nos ofrece una solución mucho más óptima: Consultas parametrizadas. Las sentencias SQL parametrizadas hacen uso de sp_executesql cuya documentación podrás encontrar en el siguiente enlace.

sp_executesql nos permite armar una sentencia sql dinámica y usar las condiciones dinámicas como si fueran parte de un procedimiento almacenado de esta manera en lugar de concatenar los valores pasados a través de los parámetros podremos colocarlos como parte de la sentencia. Para aclarar esto lo mejor es ejemplificarlo así que modificaremos el horrible procedimiento almacenado del inicio con este nuevo procedimiento:

create procedure Sp_BIEN_Tarjetas(@tipo as nvarchar(100)) as

declare @sql nvarchar(500)

set @sql = Nselect count(*)
from [Sales].[CreditCard]
where CardType = @tipo

execute sp_executesql @sql, N@tipo nvarchar(100),@tipo

De esta forma al ejecutar la misma sentencia con código sql inyectado el resultado será distinto:

SQL_Server_sp_executesql

De esta forma aseguramos que no inyecten código malintencionado en nuestros procedimientos almacenados con sentencias SQL Dinámicas incrementando con ello la seguridad.

sp_execute_sql_well_formed

 

 

Sé el primero en comentar

Deja un comentario