Injeção SQL – SQL Injection – Exemplos e como se prevenir

Tempo de Leitura: 15 Minutos

Neste artigo, vamos abordar o que é a injeção de SQL e algumas maneiras de impedir ataques dessa natureza em aplicativos Web. Ao desenvolver ou testar um site ou sistema, o objetivo é garantir que o produto está o mais protegido possível. O teste de segurança geralmente é realizado para esse fim. Para executar esse tipo de teste, inicialmente, precisamos considerar quais ataques são mais prováveis ​​de acontecer. A injeção de SQL é um desses ataques.

A injeção de SQL é considerada um dos ataques mais comuns, e pode trazer consequências sérias e prejudiciais ao sistema e aos dados armazenados.

O que é SQL Injection?

Algumas das entradas do usuário podem ser usadas no enquadramento de instruções SQL que são executadas pelo aplicativo no banco de dados. É possível que um aplicativo NÃO manipule de maneira correta as entradas fornecidas pelo usuário via um formulário, ou mesmo em uma chamada API.

Se esse for o caso, um usuário mal-intencionado poderá fornecer entradas inesperadas ao aplicativo que serão usadas para enquadrar e executar instruções SQL no banco de dados. Isso é chamado de injeção SQL. As consequências de tal ação podem ser alarmantes. Como o próprio nome indica, o objetivo do ataque de injeção SQL é injetar o código SQL malicioso.

Todo e qualquer campo de um site é como um portão para o banco de dados. No formulário de login, o usuário digita os dados de login, no campo de pesquisa o usuário digita um texto de pesquisa, no formulário de salvamento de dados, o usuário digita os dados a serem salvos. Todos esses dados indicados vão para o banco de dados.

Em vez de dados corretos, se algum código mal-intencionado for inserido, há a possibilidade de ocorrerem sérios danos ao banco de dados e a todo o sistema. A injeção de SQL é realizada com a linguagem de programação SQL (Structured Query Language) que é usada para gerenciar os dados mantidos no banco de dados. Portanto, durante esse ataque, esse código da linguagem de programação está sendo usado como uma entrada maliciosa.

Este é um dos ataques mais populares, pois os bancos de dados são usados ​​para quase todas as tecnologias, principalmente em sites de conteúdos dinâmicos e aplicativos online ou que possam guardar algum tipo de dado do usuário, ou dos utilizadores. Um aplicativo pode ter uma interface com o usuário que aceite a entrada do usuário usada para executar as seguintes tarefas:

1) Mostrar os dados armazenados relevantes para o usuário, por exemplo, o aplicativo verifica as credenciais do usuário usando as informações de login inseridas pelo usuário e expõe apenas a funcionalidade e os dados relevantes ao usuário.

2) Salvar os dados inseridos pelo usuário no banco de dados, por exemplo, assim que o usuário preencher um formulário e enviá-lo, o aplicativo continuará salvando os dados no banco de dados; esses dados são disponibilizados ao usuário na mesma sessão e nas sessões subsequentes, ou usados por exemplo para processar uma venda ou um comportamento dentro do sistema.

Com a crescente demanda por sistemas multifuncionais e independentes de plataforma, é comum que esses sistemas tenham acesso a internet e rodem em arquitetura clientes e servidores onde o banco de dados está sendo gerenciado por conexões ou aplicações SQL. E todo e qualquer aplicativo esta sujeito e esse tipo de ataque, já que diferente de uma falha que afeta um determinado sistema operacional ou aplicativo, essa falha é dependente totalmente dos desenvolvedores que devem realizar o devido tratamento dos dados em seus sistemas.

Riscos de injeção de SQL

Atualmente, bancos de dados estão sendo usado para quase todos os sistemas e sites, pois os dados devem ser armazenados em algum lugar. Como dados confidenciais estão sendo armazenados no banco de dados, há mais riscos envolvidos na segurança do sistema. Se algum site pessoal ou dados de blog forem roubados, não haverá muito dano quando comparado aos dados que seriam roubados do sistema bancário, ou dados sensíveis de usuários como históricos médicos, endereços, perfis de compra, entre uma centena de outros.

O principal objetivo desse ataque é invadir o banco de dados do sistema, portanto, as consequências desse ataque podem ser realmente prejudiciais, tanto na esfera financeira, como na esfera social ou mesmo trazer prejuízos para o fornecedor, ou proprietário do site com roubo de clientes e dados do negócio.

Quem realiza um ataque desse tipo visa algum objetivo, os mais comuns são:
-Hackear a conta de outra pessoa no sistema;
-Roubar e copiar dados confidenciais do site ou sistema;
-Alterar os dados confidenciais do sistema ou dados para quem vai realizar o pagamento;
-Excluir dados confidenciais do sistema ou contas de usuários;
-O usuário poder efetuar login no aplicativo como outro usuário, ou mesmo como administrador;
-O usuário pode visualizar informações privadas pertencentes a outros usuários, por exemplo, detalhes de perfis de outros usuários, detalhes de transações, pedidos, entre outros;
-O usuário pode alterar as informações de configuração do aplicativo e os dados dos outros usuários;
-O usuário pode modificar a estrutura do banco de dados; até excluir tabelas no banco de dados do aplicativo causando instabilidade ou queda no sistema;
-O usuário pode assumir o controle do servidor de banco de dados e executar comandos nele à vontade.

Os riscos listados acima podem realmente ser considerados sérios, pois restaurar um banco de dados ou seus dados pode custar muito. Pode custar à sua empresa uma reputação e dinheiro para restaurar os dados e o sistema perdidos. Portanto, é altamente recomendável proteger seu sistema contra esse tipo de ataque e considerar o Teste de segurança como um bom investimento na reputação do seu produto e da empresa.

Testar um sistema contra possíveis ataques é uma boa prática, mesmo que o Teste de Segurança não tenha sido planejado. Dessa forma, você pode proteger e testar o produto contra casos inesperados e usuários mal-intencionados.

A essência deste ataque

Como mencionado anteriormente, a essência desse ataque é invadir o banco de dados com propósitos maliciosos. Para executar esse teste de segurança, inicialmente, você precisa encontrar as partes vulneráveis ​​do sistema e enviar o código SQL malicioso através delas para o banco de dados. Se esse ataque for possível para um sistema, o código SQL malicioso apropriado será enviado e ações prejudiciais poderão ser executadas no banco de dados.

Todo e qualquer campo de um site é como um portão para o banco de dados. Qualquer dado ou entrada que geralmente inserimos em qualquer campo do sistema ou site vai para a consulta do banco de dados. Portanto, em vez de dados corretos, se digitarmos qualquer código malicioso, ele pode ser executado na consulta de banco de dados e trazer consequências danosas.

Como é feito o teste de Segurança

Para realizar esse ataque, precisamos alterar o ato e o objetivo de uma consulta apropriada ao banco de dados. Um dos métodos possíveis para fazer isso é tornar a consulta sempre verdadeira e depois inserir seu código malicioso. Alterar a consulta do banco de dados para sempre true pode ser realizada com um código simples como ‘or 1 = 1;  inserido em um campo destinado a entrada do usuário, como um formulário de busca ou um sistema de login ou qualquer outro dado que possa ser inserido pelo usuário.

Os testadores devem ter em mente que, ao verificar se a alteração da consulta para sempre verdadeira pode ser executada ou não, citações diferentes devem ser tentadas com diversos tipos de códigos simples e duplos. Portanto, se tentamos código como ‘or 1 = 1; –, também devemos tentar o código com aspas duplas “or 1 = 1; –.

Por exemplo , vamos considerar que temos uma consulta, que está pesquisando a palavra inserida na tabela do banco de dados: selecione * from notas as nt where nt.subject = ‘search_word’; onde search_word é a variavel que recebeu a entrada do usuário.

Portanto, em vez da palavra de pesquisa, se inserirmos uma consulta de injeção SQL ‘or 1 = 1; -, a consulta se tornará sempre verdadeira.

select * from notas as nt where nt.subject = ” or 1 = 1;

Neste caso, o parâmetro “assunto“ fecha-se com a citação e então temos o código ou 1 = 1, o que torna a consulta sempre verdadeira. Com o sinal “-“ comentamos o resto do código da consulta, que não será executado. É uma das maneiras mais populares e fáceis de começar a controlar a consulta.

Alguns outros códigos também podem ser usados ​​para tornar a consulta sempre verdadeira, como:

‘or’ abc ‘=’ abc ‘; –  ou mesmo ‘ou’ ‘=’ ‘; – porém nosso objetivo aqui não é permitir ou passar uma sequencia desses códigos, lembrando que mesmo alguns filtros mal feitos na entrada do usuário podem não bloquear todos, por isso mais de um código malicioso deve ser avaliado.

A parte mais importante aqui é que depois do sinal de vírgula podemos inserir qualquer código malicioso que gostaríamos de executar. Por exemplo: ‘ou 1 = 1; drop table notas; – este código iria eliminar a tabela notas do banco de dados se ela existir. Se essa injeção for possível, qualquer outro código malicioso pode ser escrito. Nesse caso, dependerá apenas do conhecimento e da intenção do usuário malicioso.

Como verificar a injeção de SQL?

A verificação dessa vulnerabilidade pode ser realizada muito facilmente. Às vezes, basta digitar as strings acima citadas nos campos testados. Se retornar alguma mensagem inesperada ou extraordinária, podemos ter certeza de que a injeção SQL é possível para esse campo.

Por exemplo , se você receber uma mensagem de erro como ‘Erro interno do servidor’ como resultado da pesquisa, então podemos ter certeza de que esse ataque é possível naquela parte do sistema.

Outros resultados que podem notificar um possível ataque incluem: Página em branco carregada.
Sem mensagens de erro ou sucesso – a funcionalidade e a página não reagem à entrada. Mensagem de sucesso para código malicioso. Vejamos como isso funciona na prática.

Por exemplo, vamos testar se uma janela de login apropriada é vulnerável a SQL Injection. Para tanto, no campo do endereço de e-mail ou senha, basta digitar um sinal de aspas ou aspas duplas no lugar do nome do usuário, e uma senha qualquer.

Se tal entrada retornar resultados como a mensagem de erro ‘Erro interno do servidor’ ou qualquer outro resultado inadequado listado, então podemos quase ter certeza de que esse ataque é possível para aquele campo.

Um código de injeção SQL muito complicado também pode ser tentado, existem dezenas de códigos que conseguem burlar as expressões regulares mais comuns e transcodificações que podem passar por grande parte dos códigos de filtragens válidos. Gostaria de mencionar, que em minha carreira não encontrei nenhum caso em que houvesse mensagem ‘Erro interno do servidor’ como resultado do sinal, mas às vezes os campos não reagiam para código SQL mais complicado. Portanto, verificar se há injeção de SQL com aspas simples é uma forma bastante confiável de verificar se esse ataque é possível ou não. Se a aspa simples não retornar nenhum resultado impróprio, podemos tentar inserir aspas duplas e verificar os resultados.

Além disso, o código SQL para alterar a consulta para sempre verdadeiro pode ser considerado uma forma de verificar se esse ataque é possível ou não. Ele fecha o parâmetro e altera a consulta para ‘true’. Portanto, se não for validada, tal entrada também pode retornar algum resultado inesperado e informar o mesmo, que este ataque é possível neste caso.

A verificação de possíveis ataques SQL também pode ser realizada a partir do link do site. Suponha que temos o link de um site como http://www.testing.com/books=1 . Nesse caso, ‘books’ é um parâmetro e ‘1’ é seu valor. Se no link fornecido escrevermos o sinal ‘em vez de 1, verificaremos se há possível injeção. Portanto, o link http://www.testing.com/books=’ ou http://www.txx.com/books=” será como um teste se o ataque SQL é possível para o site http://www.txx.com ou não.

Nesse caso, se o link http://www.txx.com/books= retornar uma mensagem de erro como ‘Erro interno do servidor’ ou uma página em branco ou qualquer outra mensagem de erro inesperada, também podemos ter certeza de que a injeção de SQL é possível para esse site. Posteriormente, podemos tentar enviar um código SQL mais complicado por meio do link do site. Para verificar se esse ataque é possível através do link do site ou não, códigos como ‘ou 1 = 1; – também podem ser enviados.

Teste de segurança de aplicativos da Web contra injeção de SQL

Testes de segurança de aplicativos da web explicados com exemplos simples:

Como as consequências de permitir essa técnica de vulnerabilidade podem ser graves, conclui-se que esse ataque deve ser testado durante o teste de segurança de um aplicativo. Agora, com uma visão geral dessa técnica, vamos entender alguns exemplos práticos de injeção de SQL.

Importante: Este teste de injeção de SQL deve ser testado apenas no ambiente de testes, e com o consentimento dos proprietários e usuários do site.

Se o aplicativo tiver uma página de login, é possível que o aplicativo use SQL dinâmico, como a instrução abaixo. Espera-se que esta instrução retorne pelo menos uma única linha com os detalhes do usuário da tabela Usuários como o conjunto de resultados quando houver uma linha com o nome de usuário e a senha inseridos na instrução SQL.

SELECT * from Usuarios WHERE User_Name = ‘$strUserName’ AND Password = ‘$passw’

Se o testador inserir John como strUserName (na caixa de texto para nome de usuário) e Smith como strPassword (na caixa de texto para senha), a instrução SQL acima se tornará:
SELECT * FROM Users WHERE User_Name = ‘John’ AND Password = ‘Smith’;

Se o testador inserir John’– como strUserName e qualquer valor para strPassword, a instrução SQL se tornará: SELECT * FROM Users WHERE User_Name = ‘John’ — AND Password = ‘Smith’;

Observe que a parte da instrução SQL após John é transformada em um comentário. Se houver algum usuário com o nome de usuário John na tabela Usuários, o aplicativo pode permitir que o testador efetue login como o usuário John. O testador agora pode visualizar as informações privadas do usuário John. E se o testador não souber o nome de nenhum usuário existente do aplicativo? Nesse caso, o testador pode tentar nomes de usuário comuns como admin, administrador e sysadmin. Se nenhum desses usuários existir no banco de dados, o testador pode inserir John ‘ou’ x ‘=’ x como strUserName e Smith ‘ou’ x ‘=’ x como strPassword. Isso faria com que a instrução SQL se tornasse como:
SELECT * FROM Users WHERE User_Name = ‘John’ or ‘x’=’x’ AND Password = ‘Smith’ or ‘x’=’x’;

Como a condição ‘x’ = ‘x’ é sempre verdadeira, o conjunto de resultados consistiria em todas as linhas da tabela Usuários. O aplicativo pode permitir que o testador faça login como o primeiro usuário na tabela Usuários.

Importante: o testador deve solicitar ao administrador do banco de dados ou ao desenvolvedor que copie a tabela em questão antes de tentar os ataques a seguir.

Se o testador inserir John ‘; DROP table users_details; ‘- como strUserName e qualquer coisa como strPassword, a instrução SQL se tornaria como a abaixo.
SELECT * FROM Users WHERE User_Name = ‘John’; DROP table users_details;’ –‘ AND Password = ‘Smith’;

Esta declaração pode fazer com que a tabela “users_details” seja permanentemente excluída do banco de dados.

Embora os exemplos acima lidem com o uso da técnica de injeção de SQL apenas na página de login, o testador deve testar essa técnica em todas as páginas do aplicativo que aceitam entrada do usuário em formato textual, por exemplo, páginas de pesquisa, páginas de feedback, etc.

A injeção de SQL pode ser possível em aplicativos que usam SSL. Mesmo um firewall pode não ser capaz de proteger o aplicativo contra essa técnica. Essa técnica de ataque é considerada uma forma simples. Gostaria de reiterar, que este ataque deve ser testado apenas em um ambiente de teste e não no ambiente de desenvolvimento, ou muito menos no ambiente de produção ou qualquer outro ambiente.

Em vez de testar manualmente se o aplicativo é vulnerável a ataques de SQL ou não, pode-se usar um Web Vulnerability Scanner que verifica essa vulnerabilidade. E existem centenas deles, com bancs de dados dessas pequenas sequencias que podem burlar as tratativas de inserção e filtros.

Partes vulneráveis ​​deste ataque

Antes de iniciar o processo de teste, todo testador sincero deve saber mais ou menos quais partes seriam mais vulneráveis ​​a um possível ataque. Também é uma boa prática planejar qual campo do sistema deve ser testado exatamente e em que ordem. Não é uma boa ideia testar campos contra ataques SQL aleatoriamente, pois alguns campos podem ser perdidos. Como esse ataque está sendo executado no banco de dados, todas as partes do sistema de entrada de dados, campos de entrada e links de sites estão vulneráveis. As partes vulneráveis ​​incluem: Campos de login, Campos de pesquisa,
Campos de comentário, Qualquer outra entrada de dados e campos de salvamento, Links do site.

É importante notar que ao testar esse ataque não é suficiente verificar apenas um ou alguns campos. É bastante comum que um campo esteja protegido contra SQL Injection, mas outro não. Portanto, é importante não se esquecer de testar todos os campos do site. e Com diversas formas de passagem dos dados, pois alguns filtros mais básicos podem estar feitos, porém não todos…

Automatizando testes de injeção de SQL

Como alguns sistemas ou sites testados podem ser bastante complicados e conter dados confidenciais, o teste manual pode ser muito difícil e também leva muito tempo. Portanto, testar esse ataque com ferramentas especiais pode ser muito útil às vezes.

Se tivermos testes de regressão automatizados no nível da API, também podemos alternar a verificação contra esse ataque usando estas ferramentas. Na maioria das ferramenta, já existem modelos de código preparados para verificação contra esse ataque. Esses modelos também podem ser complementados por seu próprio código escrito.

No entanto, um teste já deve ser automatizado no nível da API, o que não é tão fácil. Outra forma possível de testar automaticamente é usando vários plug-ins de navegador. Deve ser mencionado que, mesmo que as ferramentas automatizadas economizem seu tempo, nem sempre são consideradas muito confiáveis. Se estivermos testando um sistema bancário ou qualquer site com dados muito confidenciais, é altamente recomendável testá-lo manualmente. Onde você pode ver os resultados exatos e analisá-los. Além disso, neste caso, podemos ter certeza de que nada foi ignorado.

Comparação com outros ataques

O SQL Injection pode ser considerado um dos ataques mais sérios, pois influencia o banco de dados e pode causar sérios danos aos seus dados e a todo o sistema. Com certeza pode ter consequências mais sérias do que uma injeção de Javascript ou uma injeção de HTML, pois ambas são realizadas no lado do cliente. Para efeito de comparação, com este ataque, você pode ter acesso a todo o banco de dados.

Deve ser mencionado que, para testar este ataque, você deve ter um conhecimento muito bom da linguagem de programação SQL e, em geral, você deve saber como as consultas de banco de dados estão funcionando. Além disso, ao executar este ataque de injeção, você deve ser mais cuidadoso e observador, pois qualquer imprecisão pode ser deixada como vulnerabilidade SQL.

Conclusão

Espero que você tenha uma ideia clara do que é injeção de SQL e como devemos evitar esses ataques.

No entanto, é altamente recomendável testar esse tipo de ataque sempre que um sistema ou site com um banco de dados estiver sendo testado. Qualquer banco de dados perdido ou vulnerabilidade do sistema podem custar a reputação de uma empresa e muitos recursos para restaurar tudo.

Como o teste contra essa injeção ajuda a encontrar as vulnerabilidades de segurança mais importantes, também é recomendável investir em seu conhecimento e ferramentas de teste. Se o teste de segurança for planejado, o teste contra injeção de SQL deve ser planejado como uma das primeiras partes do teste.