Saltar para o conteúdo

Injeção de SQL: diferenças entre revisões

Origem: Wikipédia, a enciclopédia livre.
Conteúdo apagado Conteúdo adicionado
Injeção Duplamente "Cega" de SQL: Foi implementado uma explicação nesse Método.
Etiquetas: Inserção do elemento "nowiki", possivelmente errônea Editor Visual
Linha 131: Linha 131:


== Injeção Duplamente "Cega" de SQL ==
== Injeção Duplamente "Cega" de SQL ==
Do inglês ''Double Blind Sql Injection'', nesse método, além do invasor não visualizar os dados da base de dados através da página ''web'', ele também não obtêm carregamento de página em caso de retorno verdadeiro.
Do inglês ''Double Blind Sql Injection'', nesse método, além do invasor não visualizar os dados da base de dados (usuário e senha, por exemplo) através da página ''web'' (expostos no html, visível em tela), ele também não obtêm diferença visível na página em caso de retorno verdadeiro.
Enquanto no método anterior o invasor sabe se sua verificação booleana é verdadeira ou falsa pelo carregamento ou não da página, nesse método chamado de duplamente cego o invasor faz uma comparação de tempo de carregamento de página para saber se sua comparação que ele está enviando ao banco de dados (via método GET, por exemplo) é verdadeira ou falsa.
Enquanto no método anterior o invasor sabe se sua verificação booleana é verdadeira ou falsa pelo carregamento ou não da página, nesse método chamado de duplamente cego o invasor faz uma comparação de tempo de carregamento de página para saber se sua comparação que ele está enviando ao banco de dados (via método GET, por exemplo) é verdadeira ou falsa.

Ou seja, se a página demora 1 segundo para carregar o site "<nowiki>http://wikipedia.org/produto=1</nowiki> and 1=1" e demora metade do tempo para carregar "<nowiki>http://wikipedia.com/produto=1</nowiki> and 1=0", o invasor considera que o servidor está aceitando os comandos de injeção de SQL e sempre que tiver 1 segundo de tempo de carregamento significa que teve um retorno verdadeiro, dessa forma o invasor consegue obter caractere por caractere da senha do administrador do site.


== Ver também ==
== Ver também ==

Revisão das 17h25min de 27 de outubro de 2017

A Injeção de SQL, mais conhecida através do termo americano SQL Injection, é um tipo de ameaça de segurança que se aproveita de falhas em sistemas que interagem com bases de dados via SQL. A injeção de SQL ocorre quando o atacante consegue inserir uma série de instruções SQL dentro de uma consulta (query) através da manipulação das entradas de dados de uma aplicação.

Funcionamento

Para exemplificar o funcionamento da injeção de SQL, consideremos uma instrução SQL comum:

SELECT id, nome, sobrenome FROM autores;

Essa instrução, que representa uma consulta na base de dados, retorna todos os registros das colunas "id", "nome" e "sobrenome" da tabela "autores". A partir desta mesma instrução, os registros a serem retornados podem ser restritos através da inclusão da cláusula WHERE, como é visto no exemplo abaixo:

SELECT id, nome, sobrenome FROM autores WHERE nome = 'josé' AND sobrenome = 'silva';

Com base nesta instrução, é fácil supor que "josé" e "silva" são strings, cujo conteúdo será preenchido pela entrada feita por algum usuário que estiver fazendo uso da aplicação.

Portanto, supondo que a aplicação não faça o tratamento apropriado do conteúdo inserido pelo usuário, o mesmo pode fazer o uso acidental do caractere apóstrofo. Gerando a entrada:

  • nome = jo'sé
  • sobrenome = silva

E fazendo com que a aplicação gere o código:

SELECT id, nome, sobrenome FROM autores WHERE nome = 'jo'' AND sobrenome = 'silva';

De acordo com a especificação da linguagem SQL, existe um erro de sintaxe nessa instrução, uma vez que a string passada para o campo nome é a apenas palavra "jo", pois a adição de apóstrofo quebrou a delimitação dos apóstrofos originais da consulta. O interpretador do SQL espera que o restante da instrução seja outros comandos SQL válidos que complementem a instrução principal. No entanto, como "sé" não é um identificador válido, essa instrução não será executada e retornará um erro.

Com base neste problema, um possível atacante pode manipular os dados de entrada a fim de gerar um comportamento não esperado na base de dados.

Para exemplificar este conceito, consideremos na mesma consulta apresentada, a entrada dos seguintes dados pela aplicação:

  • nome = jo'; DROP TABLE autores ; --
  • sobrenome = silva

Fazendo com que a aplicação gere o código:

SELECT id, nome, sobrenome FROM autores WHERE nome = 'jo'; DROP TABLE autores ; --' AND sobrenome = 'silva';

Neste caso, a instrução será executada normalmente, pois não há um erro de sintaxe, no entanto, com a adição do caractere ponto-e-vírgula, a instrução foi dada como finalizada de modo prematuro dando espaço para uma nova instrução. Essa nova instrução, que poderia ser qualquer uma escolhida pelo atacante, pode ser a responsável por retornar dados confidenciais armazenados na base de dados ou de executar instruções que comprometam o sistema, como a remoção de dados e/ou tabelas, como pode ser visto no exemplo apresentado.

Aparentemente um método para prevenir esse problema seria a remoção de apóstrofos dos campos de inserção da aplicação, ou simplesmente não executando a query nestas situações. Isso é verdade, mas existem várias dificuldades com esse método tanto quanto soluções. Primeiro, nem todos os usuários inserem dados em forma de strings. Se o usuário puder selecionar um autor pelo 'id' (presumivelmente um número) por exemplo, nossa query aparecerá como abaixo:

SELECT id, forename, surname FROM authors WHERE id=1234

Nesta situação, o atacante pode simplesmente adicionar uma instrução SQL no fim do 'input' numérico. Verificando os dialetos de SQL, vários delimitadores podem ser usados no Microsoft Jet DBMS engine, por exemplo, datas podem ser delimitadas com o caracter sustenido. Portanto, escapando da execução da adição de apóstrofos, não necessariamente uma solução como demonstrado anteriormente.

Pode-se ilustrar esse ponto usando um exemplo de página de login em Active Server Pages (ASP), que acessa um servidor de banco de dados SQL e tenta autenticar o acesso em uma aplicação fictícia.

Abaixo está um pedaço de código de uma página de formulário, em que um usuário insere o username e o password para autenticação:

(...)

function Login( cn )
{
   var username;
   var password;
   username = Request.form("username");
   password = Request.form("password");
   var rso = Server.CreateObject("ADODB.Recordset");
   var sql = "select * from users where username = '" + username + "' and password = '" + password + "'";
   trace( "query: " + sql );
   rso.open( sql, cn );
   if (rso.EOF)  {
      rso.close();
   }
}

function Main()
{
//Set up connection
   var username
   var cn = Server.createobject( "ADODB.Connection" );
   cn.connectiontimeout = 20;
   cn.open( "localserver", "sa", "password" );
   username = new String( Request.form("username") );
   if( username.length > 0)  {
      Login( cn );
   }
   cn.close();
}

A parte critica é a parte do 'process_login.ascp' que cria uma 'query string':

var sql = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";

Se o usuário inserir os seguintes dados:

* Username: '; drop table users--
* Password:

... a tabela 'users' será apagada, negando o acesso para todos os usuários. A seqüência de caracteres '--' é o comentário de uma linha de SQL, a o ';' denota o fim de uma query e o começo de outra. O '--' no fim do campo username é requerido para que a query em questão seja executada sem erros.

O atacante pode logar como qualquer usuário, se souber o nome do usuário, usando o input abaixo:

  • Username: admin'--

O atacante pode logar como o primeiro usuário da tabelas 'users', com a inserção abaixo:

  • Username: ' or 1=1--

O atacante pode ainda logar como um usuário completamente fictício com o input abaixo:

  • Username: ' union select 1, 'fictional_user', 'some_password', 1--

A razão para que isso funcione é que a aplicação acredita que a linha 'constante' que o atacante especificou é parte do 'recordset' recuperado da base de dados.

Injeção de SQL Avançado

Do inglês Advanced Sql Injection, esse método consiste em explorar a injeção de instruções SQL através do método GET da página.

Através do mesmo, o invasor pode conseguir por exemplo, os dados de usuário e senha do painel administrativo do site.

Injeção "Cega" de SQL

Conhecido como Blind Sql Injection, esse método assemelha-se ao anterior, a diferença é que nesse caso a página possui uma certa segurança e o invasor não visualiza os dados da base de dados através da página web. O invasor descobre os dados desejados de 1 em 1 caractere, utilizando a função SUBSTRING do SQL em conjunto com uma verificação booliana.

Por exemplo, supondo que o usuário do sistema seja JOAO, o invasor vai ter um retorno falso com a seguinte tentativa injetada na cláusula WHERE:

... AND SELECT 1 FROM USUARIO WHERE SUBSTRING(USUARIO,1,1) = 'A'

No entanto, vai receber um retorno verdadeiro quando chegar na letra J:

... AND SELECT 1 FROM USUARIO WHERE SUBSTRING(USUARIO,1,1) = 'J'

Sabe-se que é um retorno verdadeiro porque a página é carregada normalmente, ao contrário de quando o retorno é falso.

Muitos invasores conseguem dados de usuário e senha sem ao menos ter conhecimento da teoria do método, mas apenas por utilizar a ferramenta Havij..

Injeção Duplamente "Cega" de SQL

Do inglês Double Blind Sql Injection, nesse método, além do invasor não visualizar os dados da base de dados (usuário e senha, por exemplo) através da página web (expostos no html, visível em tela), ele também não obtêm diferença visível na página em caso de retorno verdadeiro. Enquanto no método anterior o invasor sabe se sua verificação booleana é verdadeira ou falsa pelo carregamento ou não da página, nesse método chamado de duplamente cego o invasor faz uma comparação de tempo de carregamento de página para saber se sua comparação que ele está enviando ao banco de dados (via método GET, por exemplo) é verdadeira ou falsa.

Ou seja, se a página demora 1 segundo para carregar o site "http://wikipedia.org/produto=1 and 1=1" e demora metade do tempo para carregar "http://wikipedia.com/produto=1 and 1=0", o invasor considera que o servidor está aceitando os comandos de injeção de SQL e sempre que tiver 1 segundo de tempo de carregamento significa que teve um retorno verdadeiro, dessa forma o invasor consegue obter caractere por caractere da senha do administrador do site.

Ver também