Esse código impede a injeção de SQL?

fundo

Fui contratado para analisar um Provedor de Dados existente e sei que o seguinte código está com defeito; mas, para mostrar o quanto é ruim, preciso provar que é suscetível à injeção de SQL.

Questão

Qual parâmetro “Key” poderia quebrar a function PrepareString e permitir que eu execute uma instrução DROP ?

Fragmento de código

 Public Shared Function GetRecord(ByVal Key As String) As Record Dim Sql As New StringBuilder() With Sql .Append("SELECT * FROM TableName") If String.IsNullOrEmpty(Agency) Then .Append(" ORDER BY DateAdded") Else .Append(" WHERE Key = '") .Append(PrepareString(Key)) .Append("'") End If End With Return ExecuteQuery(Sql.ToString()) End Function Public Shared Function PrepareString(ByVal Value As String) As String Return Value.Replace("''", "'") _ .Replace("'", "''") _ .Replace("`", "''") _ .Replace("´", "''") _ .Replace("--", "") End Function 

Em resposta à sua pergunta direta: este código impede a injeção de SQL: Não

Aqui está a prova – envie essa string pelo método PrepareString:

 Dim input = "'" & Chr(8) & "; Drop Table TableName; - " & Chr(8) & "-" Dim output = PrepareString(input) Console.WriteLine(input) Console.WriteLine(output) 

Eu modifiquei o método GetRecord que você postou para retornar a string SQL totalmente preparada em vez de obter o registro do database:

 Console.WriteLine(GetRecord(output)) 

E esta é a saída

 Input = ; Drop Table TableName; -- Output = '; Drop Table TableName; -- Query = SELECT * FROM TableName WHERE Key = ''; Drop Table TableName; --' 

Adicione 1 linha extra de código:

 My.Computer.Clipboard.SetText(input) 

E você tem a string que precisa ser copiada para a área de transferência para colar em seu campo de input no site para concluir sua injeção de SQL:

 '; Drop Table TableName; - - 

[Observando que os caracteres de controle foram omitidos da saída do post pelo StackOverflow, então você terá que seguir o exemplo de código para criar sua saída]

Depois que o método PrepareString for executado, ele terá exatamente a mesma saída – o código ASCII Chr (8) é o backspace que removerá o extra “‘” que você está anexando ao meu, o que fechará sua string e então livre para adicionar o que eu quiser no final. Seu PrepareString não vê o meu – porque estou realmente usando – – com um caractere de backspace para remover o espaço.

O código SQL resultante que você está construindo, então, executará minha instrução Drop Table sem impedimentos e prontamente ignorará o resto da sua consulta.

A coisa divertida sobre isso é que você pode usar caracteres não imprimíveis para basicamente ignorar qualquer verificação de personagem que você possa inventar. Portanto, é mais seguro usar consultas parametrizadas (que não é o que você pediu, mas é o melhor caminho para evitar isso).

Para responder a sua pergunta questionável, não, não funcionaria.

.Replace("``", "''") impediria consultas legítimas com ‘`’

.Replace("´", "''") impediria consultas legítimas com ‘´’

.Replace("--", "") impediria consultas legítimas com ‘-‘ neles

.Replace("''", "'") modificaria incorretamente consultas legítimas com’ ” ‘neles

e assim por diante.

Além disso, o conjunto completo de caracteres de escape pode variar de um RDBMS para outro. Consultas parametrizadas FTW.

Eu acho que é unhackable se você acabou de replace ‘com’ ‘. Ouvi dizer que é possível alterar o caracter de aspas de escape, o que poderia potencialmente quebrar isso, no entanto, não tenho certeza. Eu acho que você está seguro embora.

Eu acho que é seguro (pelo menos no SQL Server), e eu também acho que a única coisa que você realmente precisa fazer é s = s.Replace("'", "''") . Claro que você deve usar consultas parametrizadas, mas você já sabe disso.

Este artigo do MSDN abrange a maioria das coisas que você precisa olhar para fora (tenho medo de dizer tudo quando se trata de injeção de SQL).

Mas vou ecoar o sentimento de todos os outros parâmetros dos parâmetros dos parâmetros.

Quanto ao seu exemplo, algumas pegadinhas [Edit: Updated these]:

  • a string “1 OR 1 = 1” não permitiria que o usuário recuperasse tudo

  • ou pior “1; drop table sometablename”

De acordo com o artigo que você deseja verificar:

; – Delimitador de consulta.

‘- Delimitador de cadeia de dados de caracteres.

– – Delimitador de comentários.

/ * … / – Delimitadores de comentários. Texto entre / e * / não é avaliado pelo servidor.

xp_ – Usado no início do nome de stored procedures estendidos por catálogo, como xp_cmdshell.

Você está tentando colocar caracteres na lista negra para implementar sua própria versão do SQL Escaping. Sugiro que você analise essa URL – o escape de SQL não é necessariamente a pior escolha (ou seja, consertar aplicativos existentes rapidamente), mas precisa ser feito corretamente para evitar vulnerabilidades.

Esse URL vincula a outra página para escape no SQL Server, onde o autor fornece sugestões que ajudam a evitar vulnerabilidades sem limitar a funcionalidade.

Se isso ajudar, os artigos sugerem que os aparelhos de escape também são chamados (chamo-os de colchetes – mas []).

Se você tentar usar seu código, alguém pode passar uma chave (; selecione * da tabela; e obtenha uma lista de qual tabela eles querem.

Em seu código, você não está verificando o ponto e vírgula, que permite terminar uma instrução t-sql e iniciar outra.

Eu iria com uma consulta parametrizada.