É verdade que os procedimentos armazenados impedem ataques de injeção SQL contra bancos de dados PostgreSQL? Pesquisei um pouco e descobri que SQL Server, Oracle e MySQL não são seguros contra injeção de SQL, mesmo que usemos apenas stored procedures. No entanto, esse problema não existe no PostgreSQL.
A implementação do procedimento armazenado no núcleo do PostgreSQL impede ataques de injeção de SQL ou é outra coisa? Ou o PostgreSQL também é suscetível à injeção de SQL, mesmo que usemos apenas procedimentos armazenados? Em caso afirmativo, mostre-me um exemplo (por exemplo, livro, site, papel, etc.).
Não, os procedimentos armazenados não impedem a injeção de SQL. Aqui está um exemplo real (de um aplicativo interno que alguém criou onde trabalho) de um procedimento armazenado que infelizmente permite a injeção de SQL:
Este código do servidor sql:
aproximadamente equivalente a postgres:
A ideia do desenvolvedor era criar um procedimento de busca versátil, mas o resultado é que a cláusula WHERE pode conter o que o usuário quiser, permitindo a visita das pequenas Bobby Tables .
Não importa se você usa instruções SQL ou procedimento armazenado. O que importa é se o seu SQL usa parâmetros ou strings concatenadas. Os parâmetros impedem a injeção de SQL; strings concatenadas permitem injeção de SQL.
Ataques de SQL-Injection são aqueles em que entradas não confiáveis são consultas diretamente anexadas, permitindo que o usuário execute efetivamente código arbitrário, conforme ilustrado neste cômico XKCD canônico.
Assim, obtemos a situação:
Procedimentos armazenados são, em geral, boas defesas contra ataques de injeção de SQL porque os parâmetros de entrada nunca são analisados.
Em um procedimento armazenado, na maioria dos bancos de dados (e programas, não se esqueça de que as consultas pré-compiladas contam como procedimentos armazenados) se parecem com o seguinte:
Então, quando o programa deseja acessar, ele chama
foo(userInput)
e recupera alegremente o resultado.Um procedimento armazenado não é uma defesa mágica contra SQL-Injection, pois as pessoas são capazes de escrever procedimentos armazenados ruins . No entanto, consultas pré-compiladas, sejam elas armazenadas no banco de dados ou no programa, são muito mais difíceis de abrir brechas de segurança se você entender como o SQL-Injection funciona.
Você pode ler mais sobre SQL-Injection:
Sim, até certo ponto.
Procedimentos armazenados sozinhos não impedirão SQL Injection.
Deixe-me primeiro citar sobre SQL Injection do OWASP
Você precisa limpar as entradas do usuário e não concatenar as instruções SQL, mesmo se estiver usando o procedimento armazenado.
Jeff Attwood explicou as consequências da concatenação do sql em " Give me parameterized SQL, or give me death "
A seguir está o desenho animado interessante que me vem à mente sempre que ouço SQL Injection , acho que você entendeu :-)
Dê uma olhada em SQL Injection Prevention Cheat Sheet , os métodos de prevenção são bem explicados...
A concatenação de strings é a causa da SQL Injection. Isso é evitado usando a parametrização.
Os procedimentos armazenados adicionam uma camada adicional de segurança, reforçando a sintaxe inválida quando você concatena, mas não são "mais seguros" se você usar, digamos, SQL dinâmico neles.
Portanto, seu código acima é causado pela concatenação dessas strings
exec sp_GetUser '
x' AND 1=(SELECT COUNT(*) FROM Client); --
' , '
monkey
'
Isso dá uma sintaxe inválida, felizmente
Parametrizando isso daria
Isso significa
@UserName
=x' AND 1=(SELECT COUNT(*) FROM Client); --
@Password
=monkey
Agora, no código acima, você não terá linhas porque presumo que você não tenha nenhum usuário
x' AND 1=(SELECT COUNT(*) FROM Client); --
Se o procedimento armazenado tiver esta aparência (usando SQL dinâmico concatenado ), sua chamada de procedimento armazenado parametrizado ainda permitirá a injeção de SQL
Então, como demonstrado, a concatenação de strings é o principal inimigo da injeção de SQL
Os procedimentos armazenados adicionam encapsulamento, manipulação de transações, permissões reduzidas, etc., mas ainda podem ser abusados para injeção de SQL.
Você pode procurar no Stack Overflow para saber mais sobre parametrização
"Ataques de injeção de SQL acontecem quando a entrada do usuário é codificada incorretamente. Normalmente, a entrada do usuário são alguns dados que o usuário envia com sua consulta, ou seja, valores em
$_GET
,$_POST
,$_COOKIE
,$_REQUEST
ou$_SERVER
arrays. No entanto, a entrada do usuário também pode vir de uma variedade de outros fontes, como soquetes, sites remotos, arquivos, etc. Portanto, você realmente deve tratar tudo, exceto constantes (como'foobar'
) como entrada do usuário ."Tenho pesquisado bastante sobre o assunto recentemente e gostaria de compartilhar com outras pessoas um material bastante interessante, tornando assim este post mais completo e instrutivo para todos.
Do YouTube
Da Wikipédia
De OWASP
Do manual do PHP
Da Microsoft e da Oracle
Estouro de Pilha
Verificador de injeção SQL
Os procedimentos armazenados não impedem magicamente a injeção de SQL, mas tornam a prevenção muito mais fácil. Tudo o que você precisa fazer é algo como o seguinte (exemplo do Postgres):
É isso! O problema só surge ao formar uma consulta por meio de concatenação de strings (ou seja, SQL dinâmico) e, mesmo nesses casos, você pode vincular! (Depende do banco de dados.)
Como evitar a injeção de SQL em sua consulta dinâmica:
Etapa 1) Pergunte a si mesmo se você realmente precisa de uma consulta dinâmica. Se você está juntando strings apenas para definir a entrada, provavelmente está fazendo errado. (Existem exceções a esta regra - uma exceção é para relatar consultas em alguns bancos de dados, você pode ter problemas de desempenho se não forçá-lo a compilar uma nova consulta a cada execução. Mas pesquise esse problema antes de entrar nisso. )
Etapa 2) Pesquise a maneira correta de definir a variável para seu RDBMS específico. Por exemplo, o Oracle permite que você faça o seguinte (citando seus documentos):
Aqui você ainda não está concatenando a entrada. Você está vinculando com segurança! Viva!
Se o seu banco de dados não suportar algo como o acima (espero que nenhum deles ainda seja tão ruim, mas não ficaria surpreso) - ou se você ainda precisar concatenar sua entrada (como no caso "às vezes" de relatar consultas como Eu sugeri acima), então você deve usar uma função de escape adequada. Não escreva você mesmo. Por exemplo, postgres fornece a função quote_literal(). Então você executaria:
Dessa forma, se in_name for algo desonesto como '[recorte] ou 1=1' (a parte "ou 1=1" significa selecionar todas as linhas, permitindo que o usuário veja os salários que não deveria!), Quote_literal salva sua bunda por fazendo a string resultante:
Nenhum resultado será encontrado (a menos que você tenha alguns funcionários com nomes realmente estranhos).
Essa é a essência disso! Agora, deixe-me deixar um link para uma postagem clássica do guru do Oracle, Tom Kyte, sobre o assunto SQL Injection, para esclarecer o ponto: Linky