Pergunta

Eu gostaria de saber se eu estou seguro contra injeção de SQL quando eu usar algo parecido com PostgresSQL:

CREATE or REPLACE FUNCTION sp_list_name( VARCHAR )
RETURNS SETOF v_player AS '
   DECLARE
      v_start_name ALIAS FOR $1;
      r_player  v_player%ROWTYPE;
      v_temp VARCHAR;
   BEGIN
      v_temp := v_start_name || ''%'';
      FOR r_player IN
         SELECT first_name, last_name FROM v_player WHERE last_name like v_temp
      LOOP
         RETURN NEXT r_player;
      END LOOP;
      RETURN;
   END;
' LANGUAGE 'plpgsql' VOLATILE;

Eu quero usar essa função para o nome início lista do jogador com uma carta.

select * from sp_list_name( 'A' );

me dá jogadores com sobrenome começando com A.

Eu tentei injetar sql com

select * from sp_list_name( 'A; delete from t_player;--' );
select * from sp_list_name( '''; delete from t_player;--' );

Am I seguro?

O que caso eu poderia ser injetado?

Saudações

Foi útil?

Solução

Em termos de seu procedimento você parece seguro como a variável no SP não será expandida dentro do código, mas você ainda pode expor a si mesmo se você não usar uma consulta parametrizada como " SELECT * FROM sp_list_name(?); "em sua código appplication . Algo como " SELECT * FROM sp_list_name('$start_name'); " poderia ser subvertida por um usuário passar um nome de início de " ');delete from t_player where last_name NOT IN (' ". Portanto, use uma consulta parametrizada ou sanidade verificar suas entradas em seu programa.

Nota: Para outros, por favor nota que uma variável em um procedimento armazenado não expandir em código mesmo se ele contém um "ou;, (excluindo passá-la para Executar , para o qual você usaria quote_literal , não-mão rolou replace funções) para a substituição; ou "é totalmente desnecessário (no procedimento armazenado, o aplicativo usando é uma história diferente, é claro) e iria impedi-lo de sempre encontrar o 'tl;dr' ou equipas 'O'Grady'.

Leo Moore, Karl, LFSR Consulting : v_temp_name no procedimento armazenado irá não ser expandida em código no SP (sem Executar ) , a verificação precisaria ser feito n o aplicativo, não o SP (ou o OP poderia usar apenas uma consulta parametrizada em seu código do aplicativo, em vez disso). O que os outros estão sugerindo é semelhante a se preocupar com

my $bar = "foo; unlink('/etc/password');"; 
my $baz = $bar;

realmente executar o unlink na ausência de um eval.

Outras dicas

Rule # 1 para prevenir contra injeção de SQL: Sanitize todas as entradas que é proveniente de alguém / algo que você não pode confiar / não tem controle sobre.

O problema em si não se encontra dentro do código de banco de dados, mas a partir da aplicação que está a executar essas declarações.

A maneira correta de proteger contra SQL Injection é via Branco Listing * - o longo e curto é definir os caracteres que você vai aceitar e filtrá-los.

A maneira incorreta é Lista Negra - Black listando quais caracteres não são aceitos é vai levar a problemas, porque não pode manter-se com os atacantes. Existem maneiras de contornar listas negras através de tabelas ASCII, caracteres de escape e quais não.

Além disso, aqui está uma boa Cheat Sheet para experimentar em seu site. Fazer alguns testes e tentar fazer as coisas a falhar.

* Na aplicação, não o DB (Graças James)

Você não está gerando SQL para si mesmo, tão seguro (para mim), esta aparência.

Eu não sei de onde os dados que você está chamando o procedimento armazenado está vindo. Então você ainda tem que se proteger contra tampão transborda etc.

Ref. Listagem branco. Este é OK, se certas outras condições forem seguidas. É absolutamente imperativo para quebrar todas as entradas para baixo na forma mais simples é tão não basta buscar por nomes de consulta SQL, aspas simples etc. Eles podem ser representadas ou codificados usando outros conjuntos de caracteres e é isso que faz parte da lista branca não especificamente palavras-chave SQL si.

Eu estava trabalhando para um determinado cliente que permitiu usuário / senha para um recurso protegido (que em última análise poderia conseguir-lhe um passe de acesso em partes seguras de um aeroporto!). Você poderia contornar o campo logon digitando 'e, em seguida, a construção de consultas SQL de lá para recuperar as contas de usuário e senhas.

O problema foi que o cliente já tinha explodido £ 200k construção do site com um fornecedor que parecia ter desenvolvimento web nunca feito antes. A correção foi um adicional de £ 60k que era uma func validate () que só foi a verificação de união, selecione, tendo et al palavras-chave. Quando perguntado sobre o que eles fizeram para canicolisation / codificação (o que eu tinha que, em seguida, explicar) que era hora tumbleweed.

A casa Dev eo (caro) Projeto foi enlatada.

Você poderia considerar validar o conteúdo de

 v_start_name 
. Verifique a string para dois pontos semi, comentário caracteres, iguais, etc. Lembre-se de verificar para ambos os Chars e os valores Hex. Lembre-se de permitir um nome com hífen, por exemplo, 'Smith-Brown' é provavelmente aceitável. 'Smith - Brown' é potencialmente injeção

Se não estiver familiarizado com Hex no SQL Injection A seguir, são introduções rápidas

http: // www .arejae.com / blog / sql-injeção-ataque utilizando-t-sql-and-hexadecimal.html

http://www.securityfocus.com/infocus/1768

DECLARE
      v_start_name ALIAS FOR $1;
      r_player  v_player%ROWTYPE;
      v_temp VARCHAR;
   BEGIN
      --  new pseudo code here
      if v_start_name has bad chars exit with error message
      -- end pseudo code here
      v_temp := v_start_name || ''%'';
      FOR r_player IN
         SELECT first_name, last_name FROM v_player WHERE last_name like v_temp
      LOOP
         RETURN NEXT r_player;
      END LOOP;
      RETURN;
   END;

Saudações Karl

Basta fazer uma substituição no seu v_start_name para se livrar da ";" etc. ie

v_clean_name VARCHAR;
Select v_clean_name = Replace(v_start_name,';','');

Este irá substituir o; com espaços em branco frustrando um ataque injecção SQL

Para mais detalhes veja Funções para String em PostgresSQL

Como LFSR Consulting também comentou. É melhor WhiteList (ou seja, não processar qualquer entrada com caracteres inválidos como um ';'). Invés de BlackList (ou seja, tente limpar os dados como o usuário poderia fazer um ataque de injeção SQL em seu Substitua também)

Para mais informações dê uma olhada no noreferrer ataques de injeção SQL

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top