Posso proteger contra Injeção de SQL por fugir aspas simples e envolvente, a entrada do usuário com aspas simples?

StackOverflow https://stackoverflow.com/questions/139199

Pergunta

Eu percebo que consultas SQL parametrizadas é a forma ideal para limpar a entrada do usuário quando a criação de consultas que contêm a entrada do usuário, mas eu estou querendo saber o que há de errado com a tomada de entrada do usuário e escapar de qualquer aspas simples e envolvente, todo o string com aspas simples.Aqui está o código:

sSanitizedInput = "'" & Replace(sInput, "'", "''") & "'"

Qualquer aspas simples o usuário entra é substituído com duas aspas simples, o que elimina a capacidade dos usuários para finalizar a seqüência de caracteres, então qualquer outra coisa que pode tipo, tais como ponto-e-vírgula, sinais de porcentagem, etc, tudo vai ser parte da seqüência de caracteres e, na verdade, não executado como parte do comando.Estamos usando o Microsoft SQL Server 2000, para o qual eu acredito que a única citação é o único delimitador de seqüência de caracteres e a única maneira de escapar do delimitador de seqüência de caracteres, então não há nenhuma maneira para executar qualquer coisa que o usuário digita.

Eu não vejo qualquer maneira para iniciar um ataque de injeção de SQL contra isso, mas eu percebo que, se este fosse como prova de balas, me parece que alguém teria pensado nisso e já seria uma prática comum.A minha pergunta é esta:o que há de errado com este código?Alguém sabe uma maneira de começar um ataque de injeção de SQL passado este higienização técnica?Exemplo de entrada do usuário que explora essa técnica pode ser muito útil.

ATUALIZAÇÃO:

Obrigado a todos por suas respostas;praticamente todas as informações que encontrei em minha pesquisa mostrou esta página em algum lugar, o que é um sinal de que a inteligência e a habilidade das pessoas que têm tido tempo de seus dias ocupados para me ajudar com esta questão.

A razão de eu ainda não aceitou nenhuma das respostas é que eu ainda não sei de qualquer maneira eficaz para lançar um ataque de injeção de SQL contra este código.Algumas pessoas sugeriram que uma barra invertida a fuga de uma única cotação e deixar as outras para finalizar a seqüência de caracteres para que o restante da seqüência de caracteres devem ser executados como parte do comando SQL, e percebo que este método de trabalho para injetar SQL em um banco de dados mySQL, mas em MS SQL 2000 a única maneira (que eu tenho sido capaz de encontrar) para escapar de uma aspa simples é com outro único-indicação;barras invertidas não fazê-lo.E, a menos que haja uma maneira de parar a escapar de um único orçamento, nenhum do resto da entrada do usuário será executado porque tudo vai ser tomada como uma cadeia de caracteres contíguos.

Eu entendo que há melhores maneiras para limpar a entrada, mas estou muito mais interessado em saber qual o método acima não funciona.Se alguém souber de alguma maneira específica para montar um ataque de injeção de SQL contra este método de higienização eu adoraria ver isso.

Foi útil?

Solução

Antes de mais nada, é apenas má prática. validação de entrada é sempre necessário, mas também é sempre duvidoso.
Pior ainda, a validação da lista negra é sempre problemática, é muito melhor para explicitamente e estritamente definir o que valores / formatos que você aceitar. Na verdade, isso nem sempre é possível - mas, até certo ponto ele deve ser sempre feito
. Alguns trabalhos de pesquisa sobre o assunto:

O ponto é, qualquer lista negra você faz (e listas brancas demasiado permissivos) pode ser ignorada. O último elo aos meus shows de papel situações onde até mesmo citar escapando pode ser ignorada.

Mesmo que estas situações não se aplicam a você, ainda é uma má idéia. Além disso, a menos que seu aplicativo é trivialmente pequeno, você vai ter que lidar com manutenção, e talvez uma certa quantidade de governança: como você garantir que o seu bem feito, em todos os lugares o tempo todo

?

A maneira correta de fazê-lo:

  • Whitelist validação: tipo, tamanho, formato ou valores aceitos
  • Se você quiser lista negra, vá em frente. Citar escapar é bom, mas dentro do contexto dos outros atenuações.
  • objetos Use comando e parâmetro, para preparse e validar
  • Chamada parametrizado consultas somente.
  • Melhor ainda, o uso de procedimentos armazenados exclusivamente.
  • Evite o uso de SQL dinâmico, e não faça concatenação uso para consultas de construção.
  • Se estiver usando SPs, você também pode limitar as permissões no banco de dados para executar única as SPs necessários, e não tabelas acessar diretamente.
  • Você também pode facilmente verificar que toda a base de código única acessa o DB através de SPs ...

Outras dicas

Ok, essa resposta vai se relacionar com a atualização da pergunta:

"Se alguém souber de qualquer maneira específica para montar um ataque de injeção SQL contra este método de sanitização Eu adoraria vê-lo."

Agora, além da barra invertida MySQL escapar - e tendo em conta que estamos na verdade falando de MSSQL, na verdade existem 3 formas possíveis de ainda SQL injetando seu código

sSanitizedInput = " 'e substituir (sInput, "'", " ''") & "'"

Leve em conta que estes não serão todas válidas em todos os momentos, e são muito dependente do seu código real em torno dele:

  1. segunda ordem SQL Injection - se uma consulta SQL é reconstruída com base em dados obtidos a partir do banco de dados depois de escapar , os dados são concatenados unescaped e pode ser indiretamente SQL-injetado. Veja
  2. Cordas truncamento - (um pouco mais complicado) - Cenário é que você tem dois campos, digamos, um nome de usuário e senha, eo SQL concatena os dois. E ambos os campos (ou apenas o primeiro) tem um limite rígido sobre comprimento. Por exemplo, o nome de utilizador está limitado a 20 caracteres. Digamos que você tenha o seguinte código:
username = left(Replace(sInput, "'", "''"), 20)

Então o que você - é o nome de usuário, escapou e, em seguida, cortado para 20 caracteres. O problema aqui - eu vou ficar minha citação no caráter 20 (por exemplo, depois de 19 a) será aparada sua cotação escapar, e (no caráter 21). Em seguida, o SQL

sSQL = "select * from USERS where username = '" + username + "'  and password = '" + password + "'"

combinado com o nome de usuário malformado referido resultará na senha já estar fora as aspas, e só vai conter a carga diretamente.
3. Unicode Contrabando - Em determinadas situações, é possível passar um personagem de alto nível unicode que aparência como uma citação, mas não - até que ele chegue ao banco de dados, onde de repente é . Uma vez que não é uma citação quando você validá-lo, ele irá passar por fácil ... Ver a minha resposta anterior para mais detalhes e link para a pesquisa original.

Em poucas palavras: Nunca faça consulta escapar-se. Você é obrigado a obter algo de errado. Em vez disso, o uso parametrizado consultas, ou se você não pode fazer isso por algum motivo, use uma biblioteca existente que faz isso para você. Não há nenhuma razão para estar fazendo isso sozinho.

Sei que este é um longo tempo após a pergunta foi feita, mas ..

Uma maneira de lançar um ataque contra o procedimento "citar o argumento é com truncamento string. De acordo com MSDN, no SQL Server 2000 SP4 (e SQL Server 2005 SP1), uma seqüência muito longa será silenciosamente truncada.

Quando você citar uma string, a string aumenta de tamanho. Cada apóstrofo é repetido. Isto pode então ser usado para empurrar partes do SQL fora do tampão. Então, você poderia efetivamente aparar partes de uma cláusula where.

Esta provavelmente seria útil principalmente em um cenário de página 'user admin' onde você pode abusar da declaração 'update' para não fazer todas as verificações que era suposto fazer.

Então, se você decidir citar todos os argumentos, verifique se você sabe o que se passa com os tamanhos de corda e fazer com que você não correr em truncagem.

Eu recomendaria indo com parâmetros. Sempre. Apenas desejo que eu poderia impor que no banco de dados. E como um efeito colateral, que são mais propensos a obter melhores acessos ao cache porque mais das demonstrações têm a mesma aparência. (Este foi certamente verdade em Oracle 8)

saneamento de entrada não é algo que você quer meia-boca. Use toda a sua bunda. Use expressões regulares sobre campos de texto. TryCast seus valores numéricos para o tipo numérico apropriado, e relatar um erro de validação, se ele não funciona. É muito fácil para procurar padrões de ataque em sua entrada, como "-. Assume toda a entrada do usuário é hostil.

Eu usei esta técnica quando se lida com a funcionalidade de 'pesquisa avançada', onde a construção de uma consulta a partir do zero foi a única resposta viável. (Exemplo: permitir que o usuário para pesquisar produtos com base em um conjunto ilimitado de restrições sobre os atributos do produto, colunas de exibição e seus valores permitidos como controles de GUI para reduzir o limiar de aprendizagem para usuários.)

Em si é seguro AFAIK. Como outro respondente ressaltou, no entanto, você pode também precisa lidar com backspace escapar (embora não ao passar a consulta para SQL Server usando ADO ou ADO.NET, pelo menos - não atestar para todos os bancos de dados ou tecnologias).

O problema é que você realmente tem que ter a certeza de que strings contêm a entrada do usuário (sempre potencialmente malicioso), e que as cordas são consultas SQL válidos. Uma das armadilhas é se você usar valores do banco de dados - foram esses valores originalmente usuário fornecido? Se assim for, eles também devem ser escapado. Minha resposta é tentar sanear o mais tarde possível (mas não mais tarde!), Ao construir a consulta SQL.

No entanto, na maioria dos casos, a ligação parâmetro é o caminho a percorrer - é apenas mais simples.

É uma má idéia de qualquer maneira como você parece saber.

Que tal algo como escapar da citação na seqüência como esta: \ '

Seu substituir resultaria em: \ ''

Se a barra invertida escapa a primeira citação, em seguida, a segunda citação terminou a string.

A resposta é simples: Ele vai trabalhar algumas vezes, mas não o tempo todo. Você quer usar a validação lista branca em tudo que você faz, mas eu percebo que nem sempre é possível, então você é forçado a ir com a melhor lista negra palpite. Da mesma forma, você quer usar procedimentos armazenados parametrizados em tudo , mas mais uma vez, isso não é sempre possível, para que você é forçado a usar sp_execute com parâmetros.

Existem maneiras de contornar qualquer lista negra utilizável que você pode vir acima com (e algumas listas brancas também).

A writeup decente é aqui: http://www.owasp.org/index. php / Top_10_2007-A2

Se você precisa fazer isso como uma solução rápida para dar-lhe tempo para obter um real no lugar, fazê-lo. Mas não pense que você está seguro.

Há duas maneiras de fazer isso, sem exceções, para ser seguro a partir do SQL-injeções; instruções preparadas ou procedimentos armazenados prameterized.

Se você tiver consultas parametrizadas disponíveis que você deve usá-los em todos os momentos. Tudo que toma é para uma consulta para deslizamento através da rede e seu DB está em risco.

Sim, que deve funcionar até que alguém executa SET QUOTED_IDENTIFIER OFF e usa aspas duplas em você.

Editar:Não é tão simples como não permitindo que o usuário mal-intencionado para desactivar a opção identificadores entre aspas:

O SQL Server Native Client driver ODBC do SQL Server Native Client Fornecedor OLE DB para SQL Server automaticamente set QUOTED_IDENTIFIER ON quando ligar.Isto pode ser configurado em fontes de dados ODBC, ODBC para conexão de atributos, ou propriedades de conexão OLE DB. O padrão para o SET QUOTED_IDENTIFIER é DESATIVADO para conexões de aplicativos de Biblioteca de banco.

Quando um procedimento armazenado é criado, o SET QUOTED_IDENTIFIER e SET ANSI_NULLS configurações são capturadas e utilizadas para invocações subseqüentes do procedimento armazenado.

SET QUOTED_IDENTIFIER também corresponde ao QUOTED_IDENTIFER definição de ALTER do BANCO de dados.

SET QUOTED_IDENTIFIER é definido no momento da análise.Definição no momento da análise significa que, se a instrução SET está presente no lote ou procedimento armazenado, ele tem efeito, independentemente de a execução de código realmente chega a esse ponto;e o CONJUNTO de instrução tem efeito antes de qualquer instruções são executadas.

Há um monte de maneiras QUOTED_IDENTIFIER pode ser desligado sem necessariamente saber.Admite - esta não é a bala de explorar o que você está procurando, mas é um grande superfície de ataque.Claro, se você também escapou aspas - então estamos de volta onde começamos.;)

Sua defesa seria um fracasso se:

  • a consulta está esperando um número em vez de uma string
  • havia qualquer outra forma de representar uma aspa, incluindo:
    • uma sequência de escape, tais como \ 039
    • um caractere Unicode

(neste último caso, ele teria que ser algo que se expandiu-se apenas depois de ter feito a sua substituir)

Patrick, você está adicionando aspas simples em torno de entrada ALL, mesmo entrada numérica? Se você tem entrada numérica, mas não estão colocando as aspas simples em torno dele, então você tem uma exposição.

O código feio tudo o que sanitização de entrada do usuário seria! Então o StringBuilder desajeitado para a instrução SQL. O método declaração preparada resulta em código mais limpo muito, e os benefícios de injeção SQL são realmente uma boa adição.

Também por reinventar a roda?

Ao invés de mudar uma única citação para (o que parece) duas aspas simples, porque não basta alterá-lo para um apóstrofo, uma citação, ou removê-lo totalmente?

De qualquer maneira, é um pouco de um truque ... especialmente quando você legitimamente têm coisas (como nomes) que pode usar aspas simples ...

NOTA:. Seu método também assume todos os que trabalham no seu aplicativo sempre se lembra de entrada sanitize antes de atingir o banco de dados, o que provavelmente não é realista na maioria das vezes

Enquanto você pode encontrar uma solução que funciona para cordas, para predicados numéricos você precisa também se certificar de que eles estão passando apenas em números (verificação simples é ele pode ser analisado como int / / decimal duplo?).

É um monte de trabalho extra.

Pode funcionar, mas parece um pouco falso para mim. Eu recomendo verifing que cada corda é válido, testando-a contra uma expressão regular em seu lugar.

Sim, você pode, se ...

Depois de estudar o assunto, eu acho entrada higienizado como você sugeriu é seguro, mas somente sob estas regras:

  1. você nunca permitir que valores de cadeia provenientes de usuários para se tornar qualquer outra coisa do que strings literais (ou seja, evitar opção de configuração dando: "Entre os nomes de coluna SQL adicionais / expressões aqui:"). outros do que cordas (números, datas ...) tipos de valor:. convertê-los para os seus tipos de dados nativos e fornecer uma rotina para literal SQL de cada tipo de dados

    • instruções SQL são problemáticos para validar
  2. você quer uso nvarchar / colunas nchar (e strings literais prefixo com N) ou valores-limite vai em colunas varchar / char para apenas caracteres ASCII (por exemplo exceção lance ao criar instrução SQL)

    • Desta forma, você estará evitando a conversão automática apóstrofe do CHAR (700) para CHAR (39) (e talvez outros hacks Unicode semelhantes)
  3. você sempre comprimento valor validar para caber comprimento da coluna real (exceção lance que mais longo)

    • havia um defeito conhecido no SQL Server permitindo ao erro de desvio SQL lançada sobre truncagem (levando a truncamento silencioso)
  4. você garante que SET QUOTED_IDENTIFIER é sempre ON

    • cuidado, ele é levado a efeito na análise de tempo, ou seja, mesmo em seções inacessíveis do código

O cumprimento destes 4 pontos, você deve ser seguro. Se você violar qualquer um deles, uma forma de injeção SQL é aberto.

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