Prevenindo SQL Injection em ASP.NET

Olá pessoal, neste artigo mostrarei como prevenir ataques de SQL Injection em aplicações ASP.NET.

Faço este artigo com base na videoaula de Bruno Belizário, do Portal Linha de Código, mediante autorização do mesmo. Acompanhem o passo-a-passo:

Conceitos – A Injeção de SQL, ou SQL Injection, é um tipo de ameaça séria de segurança, que se aproveita de falhas em sistemas (não é exclusivo pra web) que interagem com bases de dados via SQL. Dito isto, o SQL Injection ocorre quando o usuário mal intencionado consegue inserir uma série de instruções SQL dentro de uma consulta através da manipulação das entradas de dados (alterações em um textbox, por exemplo) de uma aplicação. Fonte: Wikipedia.

Prática – Feito uma breve explicação do SQL Injection, vamos a um exemplo prático. Crie uma aplicação em ASP.NET com o nome ExemploSQLInjection. Neste exemplo, irei utilizar o banco Clientes, onde tenho as tabelas Registros e Usuarios, como mostra a Figura 01:

Figura 01 – Tabelas Registros e Usuarios

Vá ao modo Design e arraste um TextBox, um Button e um GridView, para que sua página fique da seguinte forma, como mostra a Figura 02:

Figura 02 – Design da página Default.aspx

Dê o nome ao ID do botão de btnConsultar e ao Grid de dgvResultado.

Agora vá a página de códigos e crie o método para o botão Consultar:


private void Consultar()

{

try

{

//Crio a variável que irá armazenar a string de conexão

string strConn = @"Data Source=WELLINGT-45545B\SQLEXPRESS;Initial Catalog=Clientes;

Integrated Security=True;Pooling=False";

//Crio a conexão por meio do using, que me garante que após o uso, a conexão será fechada

using (SqlConnection objConn = new SqlConnection(strConn))

{

//Passo a instrução SQL por meio do SqlCommand e concateno

//meu Where com o que o usuário digitar no TextBox

SqlCommand objCmd = new SqlCommand("SELECT CODIGO, NOME FROM REGISTROS WHERE CODIGO = " +

txtConsultar.Text, objConn);

//Instancio o DataTable passando como parâmetro o SqlCommand

SqlDataAdapter objDtAdapter = new SqlDataAdapter(objCmd);

//Instancio o DataSet

DataSet ds = new DataSet();

//Uso o método Fill do DataAdapter, passando como parâmetro o DataSet e minha Tabela

objDtAdapter.Fill(ds, "REGISTROS");

//Uso o método DataSource de meu GridView, que receberá meu DataSet e chamo o DataBind

dgvResultado.DataSource = ds;

dgvResultado.DataBind();

}

}

catch (Exception ex)

{

throw new Exception(ex.Message.ToString());

}

}

Lembrando que o intuito deste artigo não é o de explicar a conexão com o banco e sim o que torna vulnerável uma aplicação por meio de SQL Injection.

Volte ao modo Design, dê dois cliques no botão Consultar e chame o método recém-criado. Salve e compile o projeto. Digite 01 no TextBox e veja o resultado, como exibe a Figura 03:

Figura 03 – Resultado de uma consulta simples no banco

O Grid é populado com os dados do Registro1. O problema é que, como ele busca o que for digitado no TextBox, se um usuário mal intencionado digitar a seguinte instrução, como mostra a Figura 04:

Figura 04 – Exemplo de SQL Injection

Fazendo isso, consigo descobrir as senhas da tabela Usuarios pois da forma como está, nossa consulta concatena tudo o que for digitado no TextBox.

Se quiser, podemos até excluir tabelas dessa forma. Dito isso, podemos concluir que nossa instrução SQL não foi feita da melhor forma, já que está vulnerável a ataques.

Para resolver isso, devemos usar a consulta parametrizada. Como o próprio nome diz, com ela nós criamos uma variável que é representada por um parâmetro, que será associado ao valor digitado no TextBox.

Para entendermos melhor, altere a instrução e adicione a seguinte linha após a instrução:


//Passo a instrução SQL por meio do SqlCommand e uso parametrização para evitar SQLInjection

SqlCommand objCmd = new SqlCommand("SELECT CODIGO, NOME FROM REGISTROS WHERE " +

"CODIGO = @CODIGO", objConn);

//Uso o método AddWithValue, que recebe meu parâmetro @Codigo e meu TextBox

objCmd.Parameters.AddWithValue("@CODIGO", txtConsultar.Text);

Como vocês podem perceber, o que mudei apenas foi usar o @Codigo, e o método AddWithValue, que recebe justamente esse parâmetro junto com o que for digitado no TextBox. Dessa forma, estamos evitando vulnerabilidades em nossa aplicação.

Compile novamente e tente digitar a instrução que usamos para fazer um Select na tabela Usuarios, como vemos na Figura 05:

Figura 05 – Exemplo da tentativa de SQL Injection na aplicação

Ao fazer isso e clicar no botão Consultar, será disparado um erro de falha de conversão, como vemos na Figura 06:

Figura 06 – Erro de conversão disparado pela aplicação

Dessa forma evitamos o uso de SQL Injection em nossa aplicação. Por isso, é altamente recomendado sempre usar parâmetros em instruções SQL.

Assim finalizo o artigo.

Para quem se interessar, disponibilizo o código fonte desse projeto aqui.

Créditos à Bruno Belizário, que fez a videoaula e ao Portal Linha de Código, por onde pude baixá-la (mediante assinatura), estudá-la e posteriormente fazer este artigo.

Quaisquer dúvidas mandem emails para wellingtonbalbo@gmail.com ou deixem nos comentários deste artigo que responderei o mais rápido possível.

Até o próximo artigo!

15 comentários em “Prevenindo SQL Injection em ASP.NET

  1. Não consigo usar isso num insert???

    Ao usar exatamente deste modo aparece erro de que o campo não pode ser nulo, ou seja, não está recebendo o valor.

    Como resolver isso?

    Curtir

    1. Rafael, o exemplo foi feito para outro fim, não para aplicar com uma cláusula de INSERT.

      Enfim, sua tabela deve estar com o campo de ID com preenchimento obrigatório, provavelmente você não está passando o valor.

      Se quiser envie seu projeto para wellingtonbalbo@gmail.com que posso tentar lhe ajudar.

      Abraços.

      Curtir

  2. Motorcycle Fairing :
    Hi there
    Thanks for writing this blog, loved reading it

    Isso ^ foi um spam.
    Eu já recebi várias dessas mensagens no meu blog e sempre recuso.
    O que eles querem é ter o link do site deles no meio do seu site (o link do usuário). Se o cara escreve em inglês provavelmente ele não leu o post, pois está em português.

    AH, sobre o seu post, aqui tem algo para complementar: http://www.developer.com/db/article.php/2243461

    Curtir

    1. Relaxa, é que realmente tem leitores americanos que acessam meu blog, por isso fico com um pé atrás pra saber se é spam ou não…

      Da mesma forma que sou portugûes e leio dezenas de artigos em inglês (você deve fazer o mesmo, como muitos outros fazem), o que impede um americano de fazer o inverso? Valeu pela dica, de qualquer forma.

      Valeu pelo link, vem acrescentar ainda mais ao artigo.

      Abraços Priscila (sim, eu fuçei seu twitter pra descobrir seu nome hehe!)

      Curtir

  3. Olá,
    após algumas semanas quebrando a cabeça com o NHibernate, volto aqui para revogar a minha sugestão, tenho descoberto que ele é uma grande e bela dor de cabeça, a não ser que você vá trabalhar com um estrutura MUITO simples e sem preocupação com desempenho, pois pelos testes que fizemos, o NHibernate não respeita o relacionamento que você faz (usando iCriteria), mas o usa apenas para exibir os dados que você relacionou, isso mesmo usando o atributo lazy=”true”, além de gerar uma query totalmente redundante, como relacionar 2 vezes as mesmas tabelas.

    A documentação é outro parto, o que se encontra (que já é bem custoso) é muito superficial e incompleto, com isso, mesmo achando a resposta, as vezes tem que continuar lendo em mais uns 2 ou 3 sites para conseguir juntar tudo, pois sempre mostram parte e nunca um todo que realmente funcione. No final das contas, algo que era para ajudar e acelerar, só atrasou, agora estamos voltando tudo pra procedure, voltando não porque não da mais tempo, mas o que ainda não foi desenvolvido será feito em proc.

    Gostaria muito de ter postado sobre outra realidade, mas é por isso que estamos passando neste exato momento.

    Curtir

  4. Seria interessante uma matéria sobre NHybernete, pois ele trata muito bem SQL Injection e ainda facilita e muito a O.O em um nível ainda mais alto.

    Curtir

  5. Seria interessante uma matéria sobre NHybernete, pois ele trata muito bem SQL Injection e ainda facilita e muito a O.O em um nível ainda mais alto.

    Curtir

Expresse sua opinião!