A dependência de consultas parametrizadas é a única maneira de se proteger contra a injeção de SQL?

13

Tudo o que vi nos ataques de injeção de SQL parece sugerir que consultas parametrizadas, principalmente as de procedimentos armazenados, são a única maneira de se proteger contra esses ataques. Enquanto eu trabalhava (na Idade das Trevas), os procedimentos armazenados eram vistos como uma prática ruim, principalmente porque eram vistos como menos sustentáveis; menos testável; altamente acoplado; e bloqueou um sistema em um fornecedor; ( esta pergunta cobre alguns outros motivos).

Embora quando eu estivesse trabalhando, os projetos praticamente não tivessem consciência da possibilidade de tais ataques; várias regras foram adotadas para proteger o banco de dados contra corrupção de vários tipos. Essas regras podem ser resumidas como:

  1. Nenhum cliente / aplicativo teve acesso direto às tabelas do banco de dados.
  2. Todos os acessos a todas as tabelas eram através de visualizações (e todas as atualizações nas tabelas base eram feitas através de gatilhos).
  3. Todos os itens de dados tinham um domínio especificado.
  4. Nenhum item de dados podia ser anulável - isso tinha implicações que os DBAs rangiam os dentes de vez em quando; mas foi aplicado.
  5. As funções e permissões foram configuradas adequadamente - por exemplo, uma função restrita para fornecer apenas às visualizações o direito de alterar os dados.

Portanto, um conjunto de regras (aplicadas) como essa (embora não necessariamente esse conjunto em particular) seja uma alternativa apropriada para consultas parametrizadas na prevenção de ataques de injeção de SQL? Se não, por que não? Um banco de dados pode ser protegido contra esses ataques por medidas específicas do banco de dados (apenas)?

EDITAR

A ênfase da pergunta mudou um pouco, à luz das respostas iniciais recebidas. Pergunta base inalterada.

EDIT2

A abordagem de confiar em consultas paramaterizadas parece ser apenas um passo periférico na defesa contra ataques a sistemas. Parece-me que as defesas mais fundamentais são desejáveis ​​e podem tornar a confiança nessas consultas desnecessária ou menos crítica, mesmo para se defender especificamente contra ataques de injeção.

A abordagem implícita na minha pergunta foi baseada em "blindar" o banco de dados e eu não tinha idéia se era uma opção viável. Pesquisas posteriores sugeriram que existem tais abordagens. Encontrei as seguintes fontes que fornecem alguns ponteiros para esse tipo de abordagem:

http://database-programmer.blogspot.com

http://thehelsinkideclaration.blogspot.com

Os principais recursos que tirei dessas fontes são:

  1. Um extenso dicionário de dados, combinado com um extenso dicionário de dados de segurança
  2. Geração de gatilhos, consultas e restrições do dicionário de dados
  3. Minimize o código e maximize os dados

Embora as respostas que recebi até o momento sejam muito úteis e apontem dificuldades decorrentes da desconsideração de consultas paramaterizadas, em última análise, elas não respondem às minhas perguntas originais (agora enfatizadas em negrito).

Chris Walton
fonte
Eu não compro os argumentos contra procedimentos armazenados. Eles simplesmente não são verdadeiros.
Konrad Rudolph
O que há com o requisito sem nulos?
Mark Canlas 21/07
2
@ Konrad Rudolph - Se você escreve seu aplicativo no MySQL e decide migrar para o DB2, você realmente acha que os procedimentos armazenados serão compatíveis? Da mesma forma, se você deseja migrar para o SQLLite? Além disso, suponha que você atualize seu sistema operacional - se seus procedimentos armazenados forem compilados em C (que estão no DB2), provavelmente todos precisarão ser recompilados. Estes são argumentos razoáveis ​​- não absolutos, mas razoáveis.
Matthew Flynn
@Matthew Duh. Na verdade, eu estava pensando em "consultas parametrizadas" ao ler isso e comentar sobre isso. Procedimento armazenado = história completa.
22911 Konrad Rudolph

Respostas:

25

Os procs armazenados não protegem automaticamente contra a injeção. E isso

CREATE PROC proc
  @id VARCHAR(5)
AS
BEGIN
  EXEC("SELECT * FROM Client WHERE ClientId = " + @id);
END

O uso de consultas parametrizadas o protegerá contra a injeção, estejam eles em procs ou não.

Craig
fonte
Obrigado pelo foco em consultas parametrizadas, em vez de procs. No entanto, estou perguntando se o banco de dados pode ser protegido por métodos que não sejam essas consultas - em particular métodos restritos apenas à camada do banco de dados.
21711 Chris Walton
1
+1 Além disso, gostaria de declarar que os procs armazenados são na maior parte considerados seguros porque é a única maneira de impedir que os usuários acessem diretamente as tabelas, mantendo uma maneira de recuperar os dados. É a única maneira de garantir privilégios com base em linhas e colunas quando o usuário precisa ter acesso direto ao banco de dados com seu cliente sem nada no meio.
Falcon
2
@ Chris - Eu acho que o que Craig está dizendo aqui é que você não pode assumir que os procs realmente o protegem. Talvez não seja uma resposta completa, mas uma correção da suposição no título.
21711 Jon Hopkins
@ Jon - alterei o título da pergunta e fiz algumas edições à pergunta, à luz da correção de Craig. Eu não estava ciente da suposição que estava fazendo na pergunta, até começar a receber respostas.
21411 Chris Walton
2
Para reforçar o que Craig escreve acima, veja databasesecurity.com/dbsec/lateral-sql-injection.pdf , "SQL Injection Lateral: uma nova classe de Vulnerabilidade no Oracle"
Bruce Ediger
11

Então, um conjunto de regras (aplicadas) como essa é uma alternativa apropriada aos procedimentos armazenados para impedir ataques de injeção de SQL? Se não, por que não?

Não, porque eles infligem uma penalidade pesada aos desenvolvedores. Um detalhamento por item:

1. Nenhum cliente / aplicativo teve acesso direto às tabelas do banco de dados.

Use funções. Os clientes só devem poder acessar o banco de dados por meio de uma função restrita que tenha acesso SELECT, INSERT, UPDATE e DELETE às tabelas (e linhas, sempre que possível) às quais ele precisa acessar. Se você deseja garantir que nenhum cliente possa enviar spam ou excluir todas as entradas, use uma API para modificação de dados.

2. Todos os acessos a todas as tabelas foram através de visualizações.

Isso pode variar de insignificante a um enorme custo de desempenho, dependendo da eficiência das visualizações. É uma complexidade desnecessária que atrasa o desenvolvimento. Use funções.

3. Todos os itens de dados tinham um domínio especificado.

Pode ser muito trabalhoso manter e provavelmente deve ser normalizado em uma tabela separada.

4. Nenhum item de dados podia ser anulável - isso tinha implicações que os DBAs rangiam os dentes de vez em quando; mas foi aplicado.

Isso é completamente errado. Se os desenvolvedores não puderem lidar com NULLs, você terá grandes problemas.

Um banco de dados pode ser protegido contra esses ataques por medidas específicas do banco de dados (apenas)?

Você não precisa de procedimentos armazenados, basta usar consultas parametrizadas com uma função que escapa aos argumentos, como pg_query_params . Obviamente, se seu banco de dados for gravável mundialmente ou se a função de cliente tiver acesso total a tudo, você estará ferrado. Alguém só precisa entender o que o cliente está fazendo e, em seguida, preparar um cliente em cinco minutos que destrói (ou pior, envenena) seu banco de dados.

l0b0
fonte
1
Domínio: en.wikipedia.org/wiki/Data_domain
Dan McGrath
+1 para funções. Eles são os principais contribuintes para isso - não incluí funções na minha pergunta, mas faziam parte da configuração - em particular, às exibições foi atribuída uma função restrita, como você sugere para os clientes. Ponto apontado no desempenho atingido das visualizações. Os domínios incluíram testes de validação - intervalos e comprimento principalmente. Seus comentários sobre a regra anulável de dados são muito mais educados do que alguns que ouvi sobre essa regra. Não afirmei explicitamente que as permissões seriam configuradas adequadamente, embora essa fosse minha suposição.
21311 Chris Walton
6

Não tenho certeza de que suas regras o protejam completamente.

O primeiro problema é que você declara que elas são aplicadas, mas, além de ter uma sobrecarga significativa, nunca vi uma aplicação perfeita.

Em segundo lugar, minha leitura deles é que regras como essas podem tornar as coisas mais difíceis de explorar, mas não as impedem. Por exemplo, não ter acesso direto às tabelas não muda muito se as visualizações permitirem o acesso aos mesmos dados. Se o cliente precisar fazer algo, uma visualização precisará facilitar isso e se a visualização facilitar, a mesma funcionalidade / dados poderão ser utilizados por um invasor.

Lembre-se também de que não se trata apenas de atualizar ou excluir dados. Parte da vulnerabilidade com a injeção de SQL é a coleta de informações e, para isso, você não se importa se os dados foram passados ​​de volta pela exibição vCustomers ou pela tabela Customers subjacente. Você pode ter se protegido de algumas fraquezas, mas não todas. Da mesma forma, se as atualizações puderem ser feitas pelo cliente, mesmo que através de gatilhos, o SQL poderá ser gravado para disparar os gatilhos e fazer atualizações.

(Em termos de todas as atualizações feitas por meio de gatilhos, vou dizer duas coisas: (1) quando li isso, fiquei com um pouco de enjoo na boca e (b) você não gosta de Procedimentos armazenados, porque eles ' re "menos manutenível; menos testável; altamente acoplado; e bloqueou um sistema em um fornecedor", mas você usa gatilhos sobre os quais basicamente podem ser ditas as mesmas coisas.)

Tudo o que você precisa é de um buraco que permita a execução de instruções SQL (e não vejo nenhuma dessas regras impedindo isso) e o invasor está dentro. Eles podem estar encontrando um banco de dados muito pouco intuitivo por trás deles, mas se eles determinarem apenas diminua a velocidade em vez de impedi-los).

A outra coisa aqui é que você também está adicionando complexidade e (assim como a sobrecarga que cria), a complexidade tende a levar a buracos que podem ser explorados.

Não estou dizendo que esse conjunto de regras não possa ser criado - mais por que você se incomodaria? Eles parecem mais pesados ​​e menos confiáveis ​​do que apenas seguir os métodos amplamente aceitos de impedir esse tipo de ataque.

Jon Hopkins
fonte
+1 por compreender minha consulta real à luz de minhas suposições implícitas e inconscientes e por responder a ela adequadamente. Quanto ao motivo pelo qual alguém pode se incomodar - estou trabalhando em um projeto em que grande parte do código será gerado a partir de uma descrição relevante da arquitetura - e parte dessa arquitetura descreve como gerar rotinas de acesso ao banco de dados. Ainda está aberto o formato que essas rotinas geradas terão.
21411 Chris Walton