sql >> Base de Datos >  >> RDS >> Mysql

SERVIDOR SQL:¿un truco para manejar SQL dinámico para evitar el ataque de inyección SQL?

SQL Server tiene tantas cosas que aprender y siempre lo encuentro increíble. Mis conversaciones con los clientes a menudo surgen con preguntas de seguridad, especialmente sobre la inyección de SQL. Muchos han afirmado que SQL Injection es un problema de SQL Server. Me toma bastante tiempo hacerles saber que no hay nada sobre SQL Server y SQL Injection. SQL Injection es el resultado de prácticas de codificación incorrectas. Una de las recomendaciones que doy es sobre no usar Dynamic SQL. Puede haber algunas situaciones en las que no puedas evitarlo. Mi único consejo sería, evitar si es posible. En este blog, demostraría un problema de inyección de SQL debido a SQL dinámico y una posible solución que puede tener.

Supongamos que tenemos una página de búsqueda simple donde el usuario puede usar la búsqueda en blanco o proporcionar un filtro en cualquier campo. Hemos proporcionado dos campos para usar "Nombre" y "Apellido". El usuario escribe algo y presiona buscar. Aquí está nuestro código de procedimiento almacenado que se activa en segundo plano.

USE AdventureWorks2014
GO
CREATE PROCEDURE search_first_or_last
@firstName NVARCHAR(50)
,@lastName NVARCHAR(50)
AS
BEGIN
DECLARE @sql NVARCHAR(4000)
SELECT @sql = ' SELECT FirstName ,MiddleName, LastName' +
' FROM Person.Person WHERE 1 = 1 '
IF @firstName IS NOT NULL
SELECT @sql = @sql + ' AND FirstName LIKE ''' + @firstName + ''''
IF @lastName IS NOT NULL
SELECT @sql = @sql + ' AND LastName LIKE ''' + @lastName + ''''
EXEC (@sql)
END

Si uso esta cadena para ejecutar en last name ”;drop table t1–

EXEC search_first_or_last '%K%', ''';drop table t1--'

La cadena dinámica sería

SELECT FirstName, MiddleName, LastName FROM Person.
Person WHERE 1 = 1 AND FirstName LIKE '%K%' AND LastName LIKE '';DROP TABLE t1--'

¿Ves el problema? Sí, los usuarios pueden eliminar la tabla t1 si el código se ejecuta en una cuenta con privilegios elevados.

Una de las soluciones al problema sería usar sp_executesql. Aquí está la mejor versión usando

CREATE PROCEDURE search_first_or_last
@firstName NVARCHAR(50)
,@lastName NVARCHAR(50)
AS
BEGIN
DECLARE @sql NVARCHAR(4000)
SELECT @sql = ' SELECT FirstName , MiddleName, LastName' +
' FROM Person.Person WHERE 1 = 1 '
IF @firstName IS NOT NULL
SELECT @sql = @sql + ' AND FirstName LIKE @firstName'
IF @lastName IS NOT NULL
SELECT @sql = @sql + ' AND LastName LIKE @lastName '
EXEC sp_executesql @sql
,N'@firstName nvarchar(50), @lastName nvarchar(50)'
,@firstName
,@lastName
END

Espero que puedas usar esto e implementarlo en tu proyecto. ¿Está utilizando estas técnicas simples en su código de producción? ¿Alguna vez ha enfrentado problemas similares durante la auditoría? Déjame saber de tus aprendizajes.