[SQL] Previniendo la Inyección de código.


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)
);
GO

Insertando 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;
GO

Resultado:

image

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.

image

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):

imageResultado 2 (Ejecuciones posteriores a la inyección simulada):

image

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:

image

Resultado 2 sin inyección de código:

image

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.

  1. No trackbacks yet.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: