Pergunta

Eu tenho algum código que utiliza consultas parametrizadas para prevenir contra a injeção, mas também precisa ser capaz de construir dinamicamente a consulta, independentemente da estrutura da tabela. Qual é a maneira correta de fazer isso?

Aqui está um exemplo, digamos que eu tenho uma tabela com colunas Nome, Endereço, Telefone. Eu tenho uma página web onde eu corro Mostrar Colunas e preencher um seleto drop-down com eles como opções.

Em seguida, eu tenho uma caixa de texto chamado Procurar . Esta caixa de texto é usado como parâmetro.

Atualmente o meu código é algo como isto:

result = pquery('SELECT * FROM contacts WHERE `' + escape(column) + '`=?', search);

Eu recebo um sentimento icky do embora. A razão que eu estou usando consultas parametrizadas é evitar o uso fuga . Além disso, fuga , provavelmente, não é projetado para escapar nomes das colunas.

Como posso garantir que isso funciona da maneira que eu pretendo?

Editar: A razão que eu requerem consultas dinâmicas é que o esquema é configurável pelo usuário, e não vou estar por perto para corrigir alguma coisa hard-coded.

Foi útil?

Solução

Em vez de passar os nomes das colunas, basta passar um identificador que você código se traduzirá em um nome de coluna usando uma tabela codificado. Isto significa que você não precisa se preocupar com dados maliciosos sendo passado, uma vez que todos os dados são ainda traduzidas legalmente, ou é conhecido por ser inválido. código Psudoish:

@columns = qw/Name Address Telephone/;
if ($columns[$param]) {
  $query = "select * from contacts where $columns[$param] = ?";
} else {
  die "Invalid column!";
}

run_sql($query, $search);

Outras dicas

O truque é ser confiante em suas escapando e validação de rotinas. Eu uso minha própria função SQL fuga que está sobrecarregado para literais de diferentes tipos. Em nenhum lugar insiro expressões (em oposição aos valores citados literais) directamente a partir da entrada de utilizador.

Ainda assim, isso pode ser feito, eu recomendo uma separada - e rigoroso - função para validar o nome da coluna. Permitir que ele para aceitar apenas um identificador único, algo como

/^\w[\w\d_]*$/

Você tem que confiar em suposições que você pode fazer sobre seus próprios nomes das colunas.

Eu uso ADO.NET eo uso de SQL Comandos e SqlParameters a esses comandos que cuidam do problema Escape. Então, se você estiver em um ambiente Microsoft-ferramenta, bem, eu posso dizer que eu uso isso muito sucesfully para SQL construção dinâmica e ainda proteger os meus parâmetros

melhor sorte

Faça a coluna com base nos resultados de outra consulta em uma tabela que enumera os valores de esquema possíveis. Nesse segundo consulta você pode codificar o selecione para o nome da coluna que é usado para definir o esquema. Se nenhuma linha é retornada então a coluna digitado é inválido.

No padrão SQL, que coloque delimitado identificadores entre aspas duplas. Isso significa que:

SELECT * FROM "SomeTable" WHERE "SomeColumn" = ?

irá seleccionar a partir de uma tabela de chamada SomeTable com o valor de mostrado (não uma versão convertida caso do nome), e vai aplicar uma condição para uma coluna chamada SomeColumn com o valor de entrega.

Por si só, isso não é muito útil, mas ... se você pode aplicar a técnica de escape () entre aspas para os nomes inseridos via seu formulário web, então você pode construir a sua consulta razoavelmente confiante.

É claro, você disse que queria evitar o uso de fuga - e na verdade você não tem que usá-lo sobre os parâmetros que você fornecer o? lugar-titulares. Mas onde você está colocando os dados fornecidos pelo usuário na consulta, você precisa para se proteger de pessoas mal-intencionadas.

Diferentes DBMS têm diferentes maneiras de fornecer identificadores delimitados. MS SQL Server, por exemplo, parece usar colchetes [SomeTable] em vez de aspas duplas.

Nomes de colunas em alguns bancos de dados podem conter espaços, o que significa que você teria que citar o nome da coluna, mas se o seu banco de dados contém nenhuma dessas colunas, basta executar o nome da coluna através de uma expressão regular ou algum tipo de verificação antes de splicing em o SQL:

if ( $column !~ /^\w+$/ ) {
  die "Bad column name [$column]";
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top