Criptografia do método GET no PHP

Minha intenção neste artigo é mostrar que podemos suprir a deficiência de segurança no método GET. Muitas pessoas acabam usando o método POST por ser mais seguro e confiável que o método GET, mas às vezes, por exemplo, quando você pega um sistema pronto e precisa fazer uma manutenção, é melhor você continuar usando o método GET do que trocar tudo por POST.

[ Hits: 93.493 ]

Por: Diego Rodrigo Machado em 24/06/2006 | Blog: http://www.bestlinux.com.br


Conclusão



Você pode utilizar o método GET de uma forma mais segura, como vimos no artigo. Mas mesmo assim não é aconselhável você usar em todo o código, por exemplo, qual seria o sentido de criptografar uma variável texto de 256 caracteres passado pelo GET? Claro... nenhuma. Neste caso, você poderia usar o método POST para fazer isso, como também poderia usar o método POST em todo o seu código.

Mas o que quis mostrar aqui é que existe uma forma mais segura para se usar o método GET. Uma forma segura usando criptografia MD5.

Essa forma de uso é extremamente eficiente quando passamos parâmetros confidenciais, como identificações, valores, status, etc.

O motivo por ser extremamente eficiente é simples. Estamos passando parâmetros como todas as outras vezes, mas só que desta vez estamos usando uma das criptografias mais usadas e mais seguras do mundo, a MD5.

Página anterior    

Páginas do artigo
   1. Introdução
   2. O problema
   3. Solução: MD5
   4. Conclusão
Outros artigos deste autor

Jogando America's Army no Linux

Jogando Wolfenstein no Linux

Leitura recomendada

Dados sensíveis em arquivos com extensão .inc

Dicas básicas de segurança no PHP

Criptografando mensagens com PHP

Autenticação de sites com PHP e MySQL

XSS - Um exemplo de ataque

  
Comentários
[1] Comentário enviado por Ragen em 25/06/2006 - 09:05h

Olá,

Legal o seu artigo =]

Mas gostaria de fazer um breve comentário. Fiquei analisando o código de encriptação por bastante tempo pra tentar entender com detalhes o que ele estava fazendo, mas então notei que seria injusto dizer que a solução é o md5. Na verdade o md5 é um "ator" do elenco de encriptação que desempenha um bom papel.

A lógica da criação dos packers/unpackers (base 16/hexadecimal) utilizando uma semente aletória em cima de uma base hexadecimal foi uma ótima sacada - Pois mata dois coelhos com uma cajadada só:

- O md5 empacota e desempacota o texto com o auxilio da funcao mt_rand(), que não utiliza a libc que por sua vez geralmente retorna sementes meio viciadas.
- O metodo de empacotamento/desempacotamento faz a colisão tender a zero.

Se você for o autor desse algoritmo, parabéns

[]'s

[2] Comentário enviado por bestlinux em 25/06/2006 - 10:26h

Ola,

"Na verdade o md5 é um "ator" do elenco de encriptação que desempenha um bom papel."

Realmente. O MD5 é um dos "atores" do codigo junto com a função base64_encode ;-)

Valeu !!

[3] Comentário enviado por pacman em 25/06/2006 - 13:46h

Não sei se eu to sonolento mas achei que podia haver alguns comentários no código. Gostaria muito de implementa-lo assim que entender como ele funciona.
Fora isso, muito bom o artigo!

[4] Comentário enviado por ijv314 em 26/06/2006 - 00:03h

Ótimo artigo!
Nunca tinha visto algo sobre como criptografar o modo GET, que realmente facilita quando se necessita fazer uma montagem rápida de páginas!
Valeu!!

[5] Comentário enviado por tomashugo em 27/06/2006 - 09:11h

Bom o artigo, gostei muito, só não entendi direito o código.
Agora vai uma sugestão, se o usuário mudar o código já criptografado, na hora de desencripitar irá retornar algo inconsistente, podendo trazer problemas para a aplicação.

Existe alguma maneira de saber se o código gerado pela encriptação está 'corrompido'?

[6] Comentário enviado por cbov em 28/06/2006 - 09:08h

http://php.net/md5

$valor=md5("teste");
$sql="select * from tabela where md5(campoDaTabela)=".$valor;

ou use direto o md5 do proprio banco ....
$sql="insert into tabela(senha) values (md5(".$_GET['senha']."))";
.....
$sql="select senha from tabela where senha=md5(".$_GET['senha'].")";
....
$sql="select md5(id) as id FROM tabela";

na minha opniao vale mais a pena tu nao saber os valores reais armazenados mas sim apenas as chaves, para depois comparar os dados para ver se as chaves batem do que este esquema de embaralhar (encriptar) e desembaralhar depois

[7] Comentário enviado por Ragen em 28/06/2006 - 11:43h

cbov,

imagina o problemão:

o usuário malicioso vê no seu sistema a seguinte url

deleteUser.php?id=funcao md5(2)


a primeira coisa que o usuário fará é um ataque de brute force nesse hash sabendo que os ids são numeros inteiros e auto incrementáveis =]

[8] Comentário enviado por bestlinux em 28/06/2006 - 11:45h

"a primeira coisa que o usuário fará é um ataque de brute force nesse hash sabendo que os ids são numeros inteiros e auto incrementáveis =] "

Pago $100000,000 para conseguir fazer um brutal force em uma criptografia MD5 ;-)

[9] Comentário enviado por Ragen em 28/06/2006 - 11:57h

bestlinux,

Pra você:

http://freshmeat.net/projects/md5bruteforcetool/
http://www.experts-exchange.com/Security/Q_21236953.html
http://www.securityfocus.com/tools/3678
http://www.governmentsecurity.org/archive/t9635.html

Além disso existem sites com word lists gigantescas que se espalham pela internet.

E sem falar no famoso John the Ripper, que faz quebra de senhas md5 utilizando brute force =]

[10] Comentário enviado por bestlinux em 28/06/2006 - 11:59h

ehehehehe..

Quem sabe, você deixa 1 ano o brutal force passando...ai quem sabe ele te retorna alguma coisa util...;-)

[11] Comentário enviado por Ragen em 28/06/2006 - 12:03h

Como não cara?

É algo bastante trivial. Existem ferramentas hoje em dia que fazem Mass Brute Force, ou seja, você faz um cluster de 100 máquinas tentando achar a senha que você precisa sem muita dificuldade.

O processo é bem simples, como a senha em questão só precisa colidir com o hash - Teoricamente existem mais de 1 senha que possuem o mesmo hash. Em outras palavras, se você possui uma senha com 1 milhão de caracteres, existe a possibilidade de você tirar o hash de uma string com 10 caracteres e haver a colisão =]

MD5 é falho quanto à colisões.

[12] Comentário enviado por bestlinux em 28/06/2006 - 12:06h

"É algo bastante trivial. Hoje existem ferramentas hoje em dia que fazem Mass Brute Force, ou seja, você faz um cluster de 100 máquinas tentando achar a senha que você precisa."

Agora você disse tudo....100 maquinas em cluster....no minimo ;-)

[13] Comentário enviado por Ragen em 28/06/2006 - 12:13h

Tá ok,

Com o script em questão - ID's de usuários auto incrementáveis - quebro tudo em menos de 10 minutos utilizando uma máquina só.

Veja a simplicidade:

deleteUser.php?id=c4ca4238a0b923820dcc509a6f75849b
deleteUser.php?id=c81e728d9d4c2f636f067f89cc14862c
deleteUser.php?id=eccbc87e4b5ce2fe28308fd9f2a7baf3
deleteUser.php?id=a87ff679a2f3e71d9181a67b7542122c
deleteUser.php?id=e4da3b7fbbce2345d7772b0674a318d5
deleteUser.php?id=1679091c5a880faf6fb5e6087eb1b2dc
deleteUser.php?id=8f14e45fceea167a5a36dedd4bea2543
deleteUser.php?id=c9f0f895fb98ab9159f51fd0297e236d
deleteUser.php?id=45c48cce2e2d7fbdea1afc51c7c6ad26
deleteUser.php?id=d3d9446802a44259755d38e6d163e820

Significa

deleteUser.php?id=1
deleteUser.php?id=2
deleteUser.php?id=3
deleteUser.php?id=4
deleteUser.php?id=5
deleteUser.php?id=6
deleteUser.php?id=7
deleteUser.php?id=8
deleteUser.php?id=9
deleteUser.php?id=10

Um pc razoavel faz fácil 1 milhão de tentativas em 10 minutos. Assim sendo, 1 milhão de ID's auto incrementáveis foram quebrados.

[14] Comentário enviado por bestlinux em 28/06/2006 - 12:15h

Mas o que acontece quando você coloca na URL

deleteUser.php?id=1

em vez de:

deleteUser.php?id=c4ca4238a0b923820dcc509a6f75849b

??

[15] Comentário enviado por Ragen em 28/06/2006 - 12:19h

Citando o problema do artigo:

"Um dia destes estava fazendo manutenção em um sistema da empresa que trabalho. Estudei o código do sistema, e vi que o programador estava usando muito o método GET. Em vários momentos, o método GET era utilizado, principalmente na edição de algum dado.

Bom... não vi problema algum, mas meu superior viu vários problemas e realmente eles existiam e eram falhas muito problemáticas.

Falha:

O programador tinha feito um código parecido com este (isto é apenas um exemplo):

<?
$con = new ConexaoMysql();
$result = $con->sql("SELECT * FROM clientes");
$dados = mysql_fetch_array($result);
$linhas = mysql_num_rows($result);
$ini = 0;

while ($linhas > $ini)
{
echo "<tr>";
$id = $dados['id'];
echo "<td bgcolor='#EEEEEE'><b>Cliente</b></td>";
echo "<td width = '12%'><a href='editar.php?id=$id'>Editar</a></td>";
echo "</tr>";
$dados = mysql_fetch_array($result);
$ini++;
}
?>

Este é apenas um código básico que lista todos os clientes da minha tabela "clientes" e ao lado do nome do Cliente, contem um link para o administrador "Editar" o Cliente. Código clássico que muitos desenvolvedores quando estão com pressa acabam usando.

O sistema em que eu estava fazendo manutenção era um sistema muito mais complexo e o problema principal da falha é que poderia ocasionar impactos "financeiros" caso o usuário alterasse o parâmetro recebido pelo GET. E realmente, este é um dos maiores problemas do método GET: O usuário que altera o parâmetro na URL."

Eu gerando os hash's de 1 até 1 milhão teria fácil os id's que preciso entre essa faixa ;)

[16] Comentário enviado por bestlinux em 28/06/2006 - 12:30h

"Eu gerando os hash's de 1 até 1 milhão teria fácil os id's que preciso entre essa faixa ;)"

eheheheeh.....você tem uma solução para tudo...eheheh....isso ai...legal....gostei dos seus comentários...;-)

[17] Comentário enviado por cbov em 28/06/2006 - 12:37h

ragen, realmente a ideia que eu passei com inteiros não ajudaria neste caso
e lembrando que o algoritimo apresentado neste artigo usa uma chave para "embaralhar" as coisas o que para passar inteiros por GET resolveria bem o problema

[18] Comentário enviado por elgio em 05/06/2007 - 12:02h

Não chame o MD5 de algoritmo de criptografia. NÃO É! É de hash!
Criptografia seriam o DES, AES, RC5, ...
No teu caso não estás usando MD5 para criptografar (e nem poderia) mas sim um simples XOR. Estás usando o MD5 para gerar uma sequencia de bits para ser aplicada ao XOR (no caso 128 bits). Logo a segurança desta criptografia está no XOR e um ataque de forma bruta seria sobre ele, com todos os vícios do XOR (em caso de repetição da chave, quebra-se; em caso de usuário ter texto cifrado + texto claro, descobre tua senha, entre outros):

$cifrado=mcrypt_ecb(MCRYPT_3DES,$ch,$texto,MCRYPT_ENCRYPT);

Onde ch é a chave, texto o texto claro.
( 3DES é super seguro, embora lento em relação aos novos como AES)
Vai no php.net Tem trocentos algoritmos de criptografia disponíveis. Ai sim estariamos fazendo com algoritmos FORTES (a segurança estaria na chave que ficaria exposta no codigo e que deve ser imprevisivel para resistir ao ataque de dicionario. Poderia usar como chave uma chave padrao+varios dados do $_SERVER, sendo a chave um hash md5 de tudo isto, ou sha1 para os que já olham o md5 de um jeito estranho...)



Se quiser mesmo ter uma segurança criptografica podes usar algoritmos reais de cifragem como o AES que já tem suporte no PHP. Para evitar usar sempre a mesma senha, poderia usar o IP de origem do cliente (ou alguma outra info do header dele) como PARTE da senha, assim clientes diferentes terão suas URL criptografadas de forma única.

[19] Comentário enviado por condelogan em 11/08/2007 - 22:47h

Um detalhe caro amigo: HASH é criptografia SIM. É a chamada criptografa de uma via. Como são resumos de plaintext, em teoria voce não pode obter o valor original atraves do resumo...Mas isso ocorre principalmente, com ataques de colisão, mas nosso amigo la em cima esta com a razão em falar que MD5 é facil de quebrar, para isso existem algoritmos de hash mais fortes como o SHA1 que o PHP oferece suporte, e gera um hash de 160 bits. Ja existem implementações em 256 bits e 512 bits....dependendo da forma como o desenvolvedor vai trabalhar, o site fica bem mais seguro, mas eu pessoalmente gosto de criar meus algoritmos de criptografia, para complicar um pouco mais e deixo hash apenas para critptografar senhas....

[20] Comentário enviado por condelogan em 12/08/2007 - 09:51h

ah, outra coisa, eu aceito o desafio para quebrar o md5, e ganhar os $100000,000 que o bestlinux ofereceu.....felizmente, tenho programa que quebra ele....e so lamento, mas md5 com seus 128 bits apenas ja esta totalmente desatualizado....

[21] Comentário enviado por elgio em 12/08/2007 - 18:47h

Caro Sandoval.
Me perdoe, mas precisarei discordar de você em dois pontos. Estou baseado em literatura e não em textos levianos da Internet.

O primeiro é a reafirmação de que MD5 não é algoritmo de criptografia. Neste ponto tu até mesmo concorda comigo quando diz que é de mão única. É isto mesmo! Uma "criptografia" que não tem volta e se não tem volta, não é criptografia. Por algoritmos de criptografia entende-se poder cifrar e decifrar e com a utilização de uma chave. O MD5 é um algorítmo de HASH (tem a sua própria denominação, como o SHA1). Algoritmos de HASH tem como características não terem chave, não serem reversíveis (o mão única) e gerarem sempre HASH de um mesmo tamanho, independente do tamanho do texto. Este tipo de algoritmo pode até usar um algoritmo de criptografia como base, como o DES, mas eles recebem sua própria denominação: HASH

Veja que estou falando de sutilezas técnicas.

O segundo ponto é sobre o MD5 poder ser quebrado.
Vos garanto que sou um profundo conhecedor do assunto, sei das recentes descobertas de colisões e dos algoritmos dos Indianos. Também CONCORDO contigo que devemos abandonar o MD5. Mas que ele foi QUEBRADO, isto não!

O programinha que tens para "quebrar" o MD5 certamente é por ataque de dicionário, tentando quebrar hashes de textos simples. Isto não é quebrar e pode ser realizado com qualquer algoritmo. O MD5 NÃO É FÁCIL DE QUEBRAR, pois iria requerer um esforço computacional de 2 elevado na 128. Não quer dizer que ele seja, atualmente, um algoritmo confiável, pois a descoberta de colisões (que é diferente de quebrar) é um risco.

Desculpe, mas eu não tenho 100 mil dolares, mas se tu conseguir quebrar este MD5
que gerei com md5sum, terei maior prazer em retirar tudo que eu disse (questão de HONRA pra ti):

echo AlgumTexto|md5sum
a5bde86f05ba9ff9bbd4fc78c5d77439

Se tu prefere no formato senhas do LINUX, te forneço também:
$1$Z.X/3YpT$O4P58NKqKlswqJAImaeTb1
(AMBOS TEM O MESMO TEXTO como base)

Quebre-o e poste-o aqui, sendo que qualquer um vai poder testar se é verdadeiro. O primeiro com echo TEXTO|md5sum e o segundo com um mkpasswd -H md5 TEXTO Z.X/3YpT

Me entenda, não estou querendo criar nenhuma polêmica barata, mas é que teoria é teoria, realmente tenho muito conhecimento da area e o que se faz é muita confusão a respeito. Lembro tambem que estou DISCORDANDO de ti quando tu diz que o MD5 pode ser facilmente quebrado (sem fornecer em QUAL CONTEXTO, devo entender que SEMPRE), mas concordo quando dizes que devemos abandonar o MD5, pois um algoritmo que se descobriu muitos furos (nenhum deles que o torne QUEBRAVEL) não merece nossa confiança.

[22] Comentário enviado por elgio em 12/08/2007 - 18:55h

Ainda, sobre o DESAFIO.

bestlinux está com a razão!
Os site que "quebram" o MD5 e até mesmo o SHA1, não QUEBRAM, ora bolas!!

Eles apenas tem listas gigantescas de textos muito usados para os quais ele já conhece. Gere um HASH com a palavra "Teste123" e VOALÁ, eles quebram.

Mais uma vez, desafio qualquer um a usar a ferramenta que quiser, o site que achar e me digam QUAL É A SENHA deste HASH MD5:

$1$Z.X/3YpT$O4P58NKqKlswqJAImaeTb1

É preciso entender as coisas. Ataques de dicinário não tem nada a ver com força bruta. Até os mais fortes algoritmos de hash serão piada se o usuário colocar a placa do carro como senha!

[23] Comentário enviado por elgio em 13/08/2007 - 09:55h

Então temos um caso em que AMBOS estamos certos, sob pontos de vistas diferentes :-D

"Em todos estes livros, HASH é considerado Criptografia..."
Sim, pertence ao estudo da Criptografia. Ambos certos. Mas não serve para Criptografar - NÃO TEM CHAVE!!!

HASH pertence ao grupo de estudo das Criptografia, mas não serve para criptografar (pois não é reversível). Na verdade ambos dizemos a mesma coisa.

Se tu estudou a fundo algoritmos de criptografia e o MD5, deve saber que um esforço de 2 na 128 ainda é um sonho e isto seria o QUEBRAR por força bruta. Não quer dizer que não se possa tentar! Se começa com cars apenas numéricos e poucas letras e vai tentando, de acordo com a paciência de quem espera e do HW que ele tem. Até mesmo o RSA de 1024 (cujo esforço computacional equivale há um simétrico de 256) pode ser tentado por força bruta.

Mas de NADA VAI ADIANTAR o força bruta se o texto contiver caracteres misturados. Quando disse "CONTEXTO", quiz me referir ao força bruta, no sentido de que PARACEU que já existem algoritmos que quebram o MD5 por força bruta em tempo razoável e para QUALQUER tipo de texto, o que não é verdade. E isto não tem nada a ver com geração de colisões, que pode ser feito em segundos.

Agora é claro que para textos pequenos, como uma senha pequena de poucos caracteres (como tu mesmo a pouco contextualizou) nem só o MD5 como qualquer outro algoritmo será quebrado por força bruta, pois o força bruta será sobre um universo de poucos cars. Como disse, NENHUM algoritmo resiste se o carinha colocar a placa do carro como senha ou o seu aniversário. :-D

[24] Comentário enviado por elgio em 13/08/2007 - 09:59h

Ainda.
Analise a solução do nosso amigo, neste artigo.
Não concorda comigo que a Criptografia usada foi XOR?
Mas que o MD5 foi apenas usado para gerar um texto "aleatório" com o qual se fez o xor? Esta foi a origem da polemica.

Disse que não se pode usar o MD5 para criptografar e não se pode mesmo!
Tu não consegue descriptografar. :-D
(como no $iv = substr($block . $iv, 0, 512) ^ $password;
Isto é UM XOR!!!)

Novamente, ambos falando a mesma coisa, mas sob contexto diferentes.

[25] Comentário enviado por condelogan em 13/08/2007 - 15:58h

Concordo com você. Hash é capaz de criptografar, só não conseguirá decriptografar...Sobre a existencia de chave, existem soluções criptograficas(obviamente inseguras), que não utilização chaves para criptografar e nem para o processo inverso, a decriptografia.

Mas sobre a solução:

Apesar de muito interressante e utilizada(já vi ela em outros foruns tambem), não podemos chama-la de solução MD5, visto que ela não usa somente a função md5(), mas a função md5_encrypt() e md5_decrypt(), e varais outras como, base64_encode e base64_decode, e se fizermos:

$texto = "qualquer coisa";
$x = md5($texto);
$y = md5_encrypt($texto);

$x e $y são totalmente diferentes.

Pessoalmente, eu usaria a função MCRYPT() - http://www.php.net/mcrypt - com o algoritmo Rijndael, ou a classe AES128, disponivel para download na internet com uma chave bastante segura.

[26] Comentário enviado por danilow em 19/10/2007 - 08:19h

Caro Diego,
creio que a função esteja com algum problema, quando codifico algo e depois decodifico fica aparecendo uns caracteres estranhos e também um "{TEXTO}"
Poderia checar por favor?

[27] Comentário enviado por dit0 em 11/12/2007 - 21:10h

Ola, cara essa solução sua vai me quebrar um galho, valeu mesmo, desse jeito podemos diminuir as vulnerabilidades causadas por scripts mal feitos ultilizando o GET. Parabéns.

[28] Comentário enviado por fabianovieiraa em 22/02/2008 - 10:12h

Ola Diego,

Tive o mesmo problema do colega Danilow... "quando codifico algo e depois decodifico fica aparecendo uns caracteres estranhos e também um "{TEXTO}" "


Pode nos dar uma ajuda quanto a isso !?

Obrigado

[29] Comentário enviado por removido em 21/01/2009 - 18:41h

Amigos já trabalhei com Bruce Schneier ( ele nem sabe o que é criptografar ) e posso falar o md5 é um algoritimo de criptografia de via unica( hash ). Nem o mais poderoso computador do mundo consequer quebrar seque o hash md5 da string 'a', mais existe muitos dicionarios completos de md5 por ai o que passa a sensação de que o mesmo é inseguro.

Mais amigo é otimo esse seu script, parabens.

Francisco Pedro da Costa Filho.

[30] Comentário enviado por removido em 21/01/2009 - 18:50h

mais o que tem de md5 aqui?

[31] Comentário enviado por lestation em 13/08/2012 - 15:51h

Creio que a melhor criptografia é a criada pelo próprio desenvolvedor

[32] Comentário enviado por elgio em 15/08/2012 - 10:08h


[32] Comentário enviado por lestation em 13/08/2012 - 15:51h:

Creio que a melhor criptografia é a criada pelo próprio desenvolvedor


Grande equívoco!


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts