¿Deberíamos seguir usando QUOTENAME para protegernos de los ataques de inyección?

9

Estaba viendo un procedimiento almacenado antiguo hoy y noté que estaba usando quotenamelos parámetros de entrada. Después de investigar un poco para descubrir qué hace exactamente, me encontré con este sitio . Ahora entiendo lo que hace y cómo usarlo, pero el sitio dice que se usa como mitigación de los ataques de inyección SQL. Cuando solía desarrollar aplicaciones que consultaban directamente una base de datos, usando asp.net, usaba los parámetros ADO.Net para pasar la entrada del usuario como un valor literal y nunca me preocupaba realmente protegerla en mis procedimientos almacenados.

Ahora estoy escribiendo un procedimiento almacenado que será utilizado por aplicaciones que no escribo, así que necesito intentar protegerme de los ataques de inyección a nivel de procedimiento, es quotenamela mejor manera de hacerlo o hay una función más nueva / mejor ¿método?

Código que me llevó a este patrón de pensamiento ( @parm1es un parámetro de entrada del usuario):

'SELECT project [Project], project_desc [Description], 
        customer [Customer], cpnyid [Company]
FROM PJPROJ (nolock)
where project like ' + quotename(@parm1,'''') + '
Matthew Verstraete
fuente

Respuestas:

17

Sí, las cosas no han cambiado mucho en esta área, debe usarlo quotenamepara cualquier nombre de objeto de servidor SQL que se use en SQL dinámico (especialmente si se suministran externamente a su código). Además de la mitigación de inyección SQL, esto también significa que su código funcionará correctamente para nombres de identificadores no estándar.

Sin embargo, la función solo es apropiada para nombres de objeto (por ejemplo, tabla, columna, nombres de bases de datos).

Debe intentar y parametrizar todo lo demás y usar sp_executesql, pasando parámetros en lugar de concatenarlos en la cadena de consulta.

El artículo definitivo sobre este tema sigue siendo The Curse and Blessings of Dynamic SQL


Editar. Ahora que ha proporcionado el código, veo que está pasando el segundo parámetro de 'agregar las comillas externas y escapar de las comillas simples duplicándolas antes de inyectarlas en la cadena. Este no es un buen uso de "nombre". Fallará (devolverá nulo) si la cadena tiene más de 128 caracteres.

Además, aún puede dejar posibilidades de inyección SQL si la cadena contiene U + 02BC en lugar del apóstrofe estándar y luego la cadena se asigna a un varchar después del saneamiento ( donde se puede convertir silenciosamente en un apóstrofo regular )

La forma correcta de hacer esto es dejar la consulta parametrizada. Y luego pasar el @parm1valor asys.sp_executesql

DECLARE @Sql NVARCHAR(MAX);

SET @Sql = '
SELECT project      [Project],
       project_desc [Description],
       customer     [Customer],
       cpnyid       [Company]
FROM   PJPROJ (nolock)
WHERE  project LIKE @parm1 
';

EXEC sys.sp_executesql
  @Sql,
  N'@parm1 varchar(100)',
  @parm1 = 'foobar%'; 
Martin Smith
fuente