Eu estava olhando para um procedimento armazenado antigo hoje e notei que estava usando quotename
os parâmetros de entrada. Depois de fazer algumas pesquisas para descobrir o que isso faz exatamente, me deparei com este site . Agora entendo o que ele faz e como usá-lo, mas o site diz que é usado como uma mitigação de ataques de SQL Injection. Quando eu costumava desenvolver aplicativos que consultavam diretamente um banco de dados, usando asp.net, eu usava os parâmetros ADO.Net para passar a entrada do usuário como um valor literal e nunca me preocupava em protegê-lo em meus procedimentos armazenados.
Agora estou escrevendo um procedimento armazenado que será usado por aplicativos que não escrevo, então preciso tentar me proteger de ataques de injeção no nível do procedimento, é quotename
a melhor maneira de fazer isso ou existe 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,'''') + '
Sim, as coisas não mudaram muito nesta área, você deve usar
quotename
para qualquer nome de objeto do servidor SQL que seja usado em SQL dinâmico (especialmente se eles forem fornecidos externamente ao seu código). Assim como a mitigação de 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 todo o resto e usar
sp_executesql
, passando parâmetros em vez de concatená-los na string de consulta.O artigo definitivo sobre este tópico ainda é The Curse and Blessings of Dynamic SQL
Editar. Agora que você forneceu o código, vejo que está passando o segundo parâmetro
'
para adicionar as 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 string for maior que 128 caracteres.Além disso, 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 ser silenciosamente convertida em um apóstrofo regular )
A forma correta de fazer isso é deixar a consulta parametrizada. E então passe o
@parm1
valor parasys.sp_executesql