Saludos amigos, encontré un ejemplo de una función escalar “Scalar User-Defined Functions”, por @Joseph Sack, la cual verifica si una instrucción TSQL esta intentando ejecutar código malintencionado que puede afectar de manera catastrófica la información y estructura de nuestras bases de datos. Como muchos de ustedes sabrán al tener sentencias TSQL no parametrizadas corremos un enorme riesgo de sufrir ataques de inyección, el script que a continuación les comparto verifica que la sentencia a ejecutar no contenga código que intente alterar los datos o la estructura de los mismos.
1. Creamos una tabla llamada DEMO_ROLES, a la cual insertaremos datos a través de Sentencias dinámicas SQL.
Creando la tabla:
USE prueba; GO CREATE TABLE dbo.DEMO_ROLES( id_rol bigint IDENTITY(1,1) NOT NULL, rol varchar(50) NOT NULL, CONSTRAINT PK_DEMO_ROLES PRIMARY KEY CLUSTERED ([id_rol] ASC) ); GOInsertando datos:
INSERT INTO dbo.DEMO_ROLES VALUES ('Administrador'), ('Gerente'), ('Supervisor'), ('Desarrollador');Seleccionando datos con “sp_executesql”.
DECLARE @SQLtext nvarchar(350); SET @SQLtext = N'SELECT * FROM dbo.DEMO_ROLES'; EXEC sp_executesql @SQLtext; GOResultado:
2. Simulando la Inyección de código. Para este paso simularemos que la cadena de código que se va a ejecutar fue modificada malintencionadamente y le concatenaron (Inyectaron) una sentencia que borra la tabla DEMO_ROLES.
Ejecutando la sentencia:
DECLARE @SQLtext nvarchar(350); SET @SQLtext = N'SELECT * FROM dbo.DEMO_ROLES' + ';DROP TABLE dbo.DEMO_ROLES'; EXEC sp_executesql @SQLtext; GO
Nota: Por el orden en el que se ejecutan las sentencias, primero se seleccionan los datos y después se elimina la tabla, por lo tanto hasta la próxima ejecución de las sentencias se producirá una excepción donde el SQL nos indicara que la tabla DEMO_ROLES no existe, esto a cause de que fue eliminada por la simulación de la inyección de código.
Resultado 1 (Primera ejecución con inyección simulada):
Resultado 2 (Ejecuciones posteriores a la inyección simulada):
Ahora como lo resolvemos:
1. Para esto tenemos que crear la tabla DEMO_ROLES, e insertar los datos (vea la parte inicial del Post).
2. Crear una función escalar la cual se encargara de verificar si las sentencias a ejecutar son maliciosas y contienen código que pueda alterar nuestra base de datos.
USE prueba; GO CREATE FUNCTION [dbo].[udf_CheckForSQLInjection] (@TSQLString varchar(max)) RETURNS BIT AS BEGIN DECLARE @IsSuspect bit -- UDF assumes string will be left padded with a single space SET @TSQLString = ' ' + @TSQLString IF (PATINDEX('% xp_%' , @TSQLString ) <> 0 OR PATINDEX('% sp_%' , @TSQLString ) <> 0 OR PATINDEX('% DROP %' , @TSQLString ) <> 0 OR PATINDEX('% GO %' , @TSQLString ) <> 0 OR PATINDEX('% INSERT %' , @TSQLString ) <> 0 OR PATINDEX('% UPDATE %' , @TSQLString ) <> 0 OR PATINDEX('% DBCC %' , @TSQLString ) <> 0 OR PATINDEX('% SHUTDOWN %' , @TSQLString )<> 0 OR PATINDEX('% ALTER %' , @TSQLString )<> 0 OR PATINDEX('% CREATE %' , @TSQLString ) <> 0OR PATINDEX('%;%' , @TSQLString )<> 0 OR PATINDEX('% EXECUTE %' , @TSQLString )<> 0 OR PATINDEX('% BREAK %' , @TSQLString )<> 0 OR PATINDEX('% BEGIN %' , @TSQLString )<> 0 OR PATINDEX('% CHECKPOINT %' , @TSQLString )<> 0 OR PATINDEX('% BREAK %' , @TSQLString )<> 0 OR PATINDEX('% COMMIT %' , @TSQLString )<> 0 OR PATINDEX('% TRANSACTION %' , @TSQLString )<> 0 OR PATINDEX('% CURSOR %' , @TSQLString )<> 0 OR PATINDEX('% GRANT %' , @TSQLString )<> 0 OR PATINDEX('% DENY %' , @TSQLString )<> 0 OR PATINDEX('% ESCAPE %' , @TSQLString )<> 0 OR PATINDEX('% WHILE %' , @TSQLString )<> 0 OR PATINDEX('% OPENDATASOURCE %' , @TSQLString )<> 0 OR PATINDEX('% OPENQUERY %' , @TSQLString )<> 0 OR PATINDEX('% OPENROWSET %' , @TSQLString )<> 0 OR PATINDEX('% EXEC %' , @TSQLString )<> 0) BEGIN SELECT @IsSuspect = 1 END ELSE BEGIN SELECT @IsSuspect = 0 END RETURN (@IsSuspect) END; GO
3. Ejecutando las sentencias TSQL con la ayuda de la función para verificar la inyección de código.
DECLARE @SQLtext nvarchar(350); SET @SQLtext = N'SELECT * FROM dbo.DEMO_ROLES' + ';DROP TABLE dbo.DEMO_ROLES'; IF dbo.udf_CheckForSQLInjection(@SQLtext) = 1 BEGIN PRINT ('Advertencia: El código es sospecho de contener código malicioso (TSQL Inyection).') END ELSE BEGIN EXEC sp_executesql @SQLtext; END
Resultado 1 con inyección de código:
Resultado 2 sin inyección de código:
![]()
Pueden hacer la modificaciones que crean necesarias a la función de inyección de código, ya que el funcionamiento y validación depende de las necesidades que deseemos cubrir.
Bueno amigos me despido y con gusto espero comentarios, por favor apóyenme votando por mi blog en http://blogit.ms en la categoría de SQL Server.
Comentarios recientes