Ainda devemos usar QUOTENAME para proteger contra ataques de injeção?

9

Eu estava olhando para um antigo procedimento armazenado hoje e notei que estava usando quotenameos parâmetros de entrada. Depois de fazer algumas escavações para descobrir o que isso faz exatamente me deparei com este site . Agora eu entendo o que ele faz e como usá-lo, mas o site diz que é usado como atenuação de ataques de injeção de SQL. Quando desenvolvia aplicativos que consultavam diretamente um banco de dados, usando o asp.net, usava os parâmetros do ADO.Net para transmitir a entrada do usuário como um valor literal e nunca me preocupava em protegê-lo nos meus procedimentos armazenados.

Agora estou escrevendo um procedimento armazenado que será usado por aplicativos que não escrevo, por isso preciso tentar me proteger de ataques de injeção no nível do procedimento, é quotenamea melhor maneira de fazer isso ou há uma função mais nova / melhor método?

Código que me levou a esse padrão de pensamento ( @parm1é um parâmetro de entrada do usuário):

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

Respostas:

17

Sim, as coisas não mudaram muito nessa área; você deve usar quotenamequalquer nome de objeto do servidor SQL usado no SQL dinâmico (especialmente se eles forem fornecidos externamente ao seu código). Além da atenuação da injeção de SQL, isso também significa que seu código funcionará corretamente para nomes de identificadores não padrão.

A função é apropriada apenas para nomes de objetos (por exemplo, tabela, coluna, nomes de banco de dados).

Você deve tentar parametrizar tudo o mais e usar sp_executesql, passando parâmetros em vez de concatená-los na cadeia de caracteres da consulta.

O artigo definitivo sobre este tópico ainda é A maldição e as bênçãos do SQL dinâmico


Editar. Agora você forneceu o código que vejo que está passando o segundo parâmetro de 'para adicionar aspas externas e escapar de aspas simples, dobrando-as antes de injetá-las na string. Este não é um bom uso de quotename. Ele falhará (retornará nulo) se a sequência tiver mais de 128 caracteres.

Além disso, ele ainda pode deixar possibilidades de injeção de SQL se a string contiver U + 02BC em vez do apóstrofo padrão e, em seguida, a string for atribuída a um varchar após o saneamento ( onde pode silenciosamente ser convertida em apóstrofo regular )

A maneira correta de fazer isso é deixar a consulta parametrizada. E depois passe o @parm1valor parasys.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
fonte