FlawOpen

flawopen.com/Inyección SQL/Procedimientos almacenados

¿Los procedimientos almacenados evitan la inyección SQL?

Página de referencia
Respuesta breve

No; es una idea equivocada muy común. Un procedimiento almacenado protege solo si usa parámetros enlazados internamente. Si concatena sus entradas en una cadena de consulta y la ejecuta con EXEC o sp_executesql, es tan vulnerable como concatenar cadenas en la aplicación.

INSEGURO — concatena el valor en SQL dinámico
-- SQL Server T-SQL; dbo.Users.Id is NVARCHAR(50).
CREATE PROCEDURE dbo.GetUser
  @UserId NVARCHAR(50)
AS
BEGIN
  DECLARE @sql NVARCHAR(MAX) =
    N'SELECT Id FROM dbo.Users WHERE Id = N'''
      + @UserId + N'''';
  EXEC(@sql);
END;
SEGURO — enlaza un parámetro con sp_executesql
-- SQL Server T-SQL; same illustrative schema.
CREATE PROCEDURE dbo.GetUser
  @UserId NVARCHAR(50)
AS
BEGIN
  DECLARE @sql NVARCHAR(MAX) =
    N'SELECT Id FROM dbo.Users WHERE Id = @id';
  EXEC sys.sp_executesql
    @stmt = @sql,
    @params = N'@id NVARCHAR(50)',
    @id = @UserId;
END;

Por qué es común esta idea equivocada

“Usa procedimientos almacenados” suele repetirse como solución general a la inyección SQL. Funciona si el procedimiento pasa los valores como parámetros enlazados en una consulta normal. Si construye SQL dinámico con EXEC y concatena valores no confiables, reintroduce el mismo riesgo. Cuando el SQL dinámico sea necesario, enlaza valores con sp_executesql. Los nombres de tablas y columnas no se pueden enlazar como valores; asigna las opciones permitidas a identificadores fijos mediante una lista de permitidos.

Preguntas frecuentes

¿sp_executesql puede ser seguro?

Sí. sp_executesql admite parámetros: decláralos y pasa los valores por separado (por ejemplo, EXEC sp_executesql @sql, N'@id INT', @id = @UserId). No concatentes valores en @sql. Para nombres dinámicos de tabla o columna, usa una lista de permitidos estricta porque los identificadores no son parámetros enlazables.

Referencias

Véase también Inyección SQL (CWE-89): cómo funciona y cómo evitarla en cada lenguaje — flawopen.com ¿El QueryBuilder de TypeORM es seguro frente a SQL Injection? Django ORM y SQL Injection: patrones seguros Inyección SQL en Doctrine ORM: consultas seguras EF Core FromSqlRaw: SQL parametrizado seguro FastAPI y SQL Injection: qué protege Pydantic GORM Raw SQL: evita la inyección SQL en Go