Eu li em várias fontes que a saída do rand () do PHP é previsível como PRNG, e eu geralmente aceito isso como fato simplesmente porque eu a vi em muitos lugares.
Estou interessado em uma prova de conceito: como eu previa a saída de rand ()? Ao ler este artigo , entendo que o número aleatório é um número retornado de uma lista que começa em um ponteiro (a semente) - mas não consigo imaginar como isso é previsível.
Alguém poderia descobrir razoavelmente qual # aleatório foi gerado via rand () em um determinado momento dentro de alguns milhares de palpites? ou até 10.000 palpites? Quão?
Isso está chegando porque vi uma biblioteca de autenticação que usa rand () para produzir um token para usuários que perderam senhas e presumi que isso fosse uma falha de segurança em potencial. Desde então, substituí o método por hash, uma mistura de openssl_random_pseudo_bytes()
senha de hash original e microtime. Depois de fazer isso, percebi que, se estivesse olhando de fora, não teria idéia de como adivinhar o token, mesmo sabendo que era um md5 de rand ().
Respostas:
A capacidade de adivinhar o próximo valor
rand
está ligada à capacidade de determinar o quesrand
foi chamado. Em particular, a propagaçãosrand
com um número predeterminado resulta em resultados previsíveis ! No prompt interativo do PHP:Isso não é apenas um acaso. A maioria das versões do PHP * na maioria das plataformas ** gerará a sequência 97, 97, 39, 77, 93 quando
srand
usada com 1024.Para ser claro, isso não é um problema com o PHP, é um problema com a implementação em
rand
si. O mesmo problema aparece em outros idiomas que usam a mesma implementação (ou similar), incluindo Perl.O truque é que qualquer versão sã do PHP terá pré-propagada
srand
com um valor "desconhecido". Ah, mas não é realmente desconhecido. Deext/standard/php_rand.h
:Então, é um pouco de matemática com
time()
, o PID e o resultado dephp_combined_lcg
, que é definido emext/standard/lcg.c
. Eu não vou c & p aqui, bem, meus olhos vidraram e eu decidi parar de caçar.Um pouco de pesquisa no Google mostra que outras áreas do PHP não têm as melhores propriedades de geração de aleatoriedade , e chamadas para
php_combined_lcg
se destacar aqui, especialmente esta parte da análise:Sim isso
uniqid
. Parece que o valor dephp_combined_lcg
é o que vemos quando olhamos para os dígitos hexadecimais resultantes depois de chamaruniqid
com o segundo argumento definido como um valor verdadeiro.Agora onde estávamos?
Ai sim.
srand
.Portanto, se o código do qual você está tentando prever valores aleatórios não for chamado
srand
, será necessário determinar o valor fornecido pelophp_combined_lcg
qual você pode obter (indiretamente?) Através de uma chamada parauniqid
. Com esse valor em mãos, é possível forçar o restante do valor -time()
, o PID e algumas contas. O problema de segurança vinculado é sobre interromper as sessões, mas a mesma técnica funcionaria aqui. Novamente, a partir do artigo:Apenas substitua a última etapa, conforme necessário.
(Esse problema de segurança foi relatado em uma versão anterior do PHP (5.3.2) do que a atual (5.3.6); portanto, é possível que o comportamento de
uniqid
e / ouphp_combined_lcg
tenha sido alterado, portanto, essa técnica específica pode não ser mais viável. YMMV.)Por outro lado, se o código para o qual você está tentando produto ligar
srand
manualmente , a menos que eles estejam usando algo muitas vezes melhor que o resultadophp_combined_lcg
, provavelmente será mais fácil adivinhar o valor e semear seu local gerador com o número certo. A maioria das pessoas que telefonaria manualmentesrand
também não perceberia o quão horrível é uma ideia e, portanto, provavelmente não usará valores melhores.Vale ressaltar que
mt_rand
também é afetado pelo mesmo problema. A propagaçãomt_srand
com um valor conhecido também produzirá resultados previsíveis. Basear sua entropiaopenssl_random_pseudo_bytes
é provavelmente uma aposta mais segura.tl; dr: Para obter melhores resultados, não propague o gerador de números aleatórios PHP e, pelo amor de Deus, não exponha
uniqid
aos usuários. Se você fizer um ou os dois, poderá tornar seus números aleatórios mais fáceis de adivinhar.Atualização para o PHP 7:
O PHP 7.0 apresenta
random_bytes
erandom_int
como principais funções. Eles usam a implementação CSPRNG do sistema subjacente, liberando-os dos problemas que um gerador de números aleatórios semeado tem. Eles são efetivamente semelhantesopenssl_random_pseudo_bytes
, apenas sem a necessidade de instalar uma extensão. Um polyfill está disponível para PHP5 .*: O patch de segurança Suhosin altera o comportamento de
rand
e demt_rand
modo que eles sempre sejam reproduzidos novamente a cada chamada. Suhosin é fornecido por terceiros. Algumas distribuições Linux o incluem em seus pacotes oficiais do PHP por padrão, enquanto outras o tornam uma opção e outras o ignoram completamente.**: Dependendo da plataforma e das chamadas de biblioteca subjacentes que estão sendo usadas, serão geradas sequências diferentes das documentadas aqui, mas os resultados ainda deverão ser repetidos, a menos que o patch Suhosin seja usado.
fonte
Para ilustrar visualmente o quão aleatória é a
rand()
função, aqui está uma imagem em que todos os pixels são feitos de valores "aleatórios" de vermelho, verde e azul:Normalmente não deve haver nenhum padrão nas imagens.
Eu tentei chamar
srand()
com valores diferentes, isso não muda a previsibilidade dessa função.Observe que ambos não são criptograficamente seguros e produzem resultados previsíveis.
fonte
É um gerador de congruência linear . Isso significa que você tem uma função que é efetivamente:
NEW_NUMBER = (A * OLD_NUMBER + B) MOD C
. Se você traçar NEW_NUMBER vs OLD_NUMBER, começará a ver linhas diagonais. Algumas das notas na documentação RAND do PHP fornecem exemplos de como fazer isso.Em uma máquina Windows, o valor máximo de RAND é 2 ^ 15. Isso oferece ao atacante apenas 32.768 possibilidades de verificação.
Embora este artigo não seja exatamente o que você está procurando, mostra como alguns pesquisadores pegaram uma implementação existente de um gerador de números aleatórios e a usaram para ganhar dinheiro com o Texas Holdem. Existem 52! possíveis decks embaralhados, mas a implementação usou um gerador de números aleatórios de 32 bits (que é o número máximo de mt_getrandmax em uma máquina Windows) e o propagou com o tempo em milissegundos desde a meia-noite. Isso reduziu o número de decks embaralhados possíveis de cerca de 2 ^ 226 para cerca de 2 ^ 27, possibilitando pesquisar em tempo real e saber qual deck foi tratado.
Eu recomendo usar algo da família SHA-2, pois os federais consideram o MD5 quebrado. Algumas pessoas usam o google para descriptografar os hashes do md5 porque são muito comuns. Basta fazer algo com hash e depois jogá-lo em uma pesquisa no Google - basicamente, o Google se tornou uma gigantesca tabela arco-íris .
fonte
É realmente mais preciso dizer que, dado um número gerado aleatoriamente, o próximo é relativamente previsível. Existem tantos números que podem ser. Mas isso não significa que você possa adivinhar, mais do que escrever um programa que o faça, muito rapidamente.
fonte