Injeção de SQL: diferenças entre revisões
substituição de "aspas simples" por "apóstrofo" |
|||
Linha 128: | Linha 128: | ||
Sabe-se que é um retorno verdadeiro porque a página é carregada normalmente, ao contrário de quando o retorno é falso. |
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 - Advanced SQL Injection|Havij]]. |
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 - Advanced SQL Injection|Havij]].. |
||
== Ver também == |
== Ver também == |
Revisão das 16h42min de 2 de setembro de 2015
Este artigo não cita fontes confiáveis. (Agosto de 2010) |
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'sé' 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 do 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 booleana.
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..