2015-05-09 12 views
10

L'utilizzo di srand(time()) per generare un token per la reimpostazione della password (o per un token CSRF) non è corretto perché il token può essere prevedibile.Perché srand (time()) è un cattivo seme?

ho letto queste:

Ma io non capisco come il token può essere prevedibile. Capisco che se in un secondo resento la mia password molte volte ottengo lo stesso token. Ho il seguente codice:

<?php 

srand(time()); 
$reset_password_token = rand(444444444444,999999999999); 

?> 

Se reimposta la password di molte volte in un secondo, so che ho la stessa ragione, ma come può un hacker può sfruttare questa?

+0

Il seme è solo un problema. L'uso di 'rand' stesso, anche con un seme imprevedibile, è una vulnerabilità di sicurezza. –

risposta

13

Limita l'ambito della loro forza bruta. Ad esempio, devono solo tentare solo 60 password se sanno che qualcuno ha effettuato un reset nell'ultimo minuto.

Ma è peggio di così. L'utente malintenzionato può accedere a qualsiasi account desiderato avviando una reimpostazione della password per tale account. Dopo questo, generano alcuni token chiamando ripetutamente srand con il timestamp unix per una piccola finestra di tempo attorno al reset, incrementando ogni volta. Uno di quei token deve corrispondere a meno che il tuo orologio non sia lontano.

+0

Supose So esattamente il timestamp e conosco il generatore dell'algoritmo (numero di intervallo come il mio esempio). Se ho capito, se provo questo: 'while (1) {// Genere un nuovo token e catturare il timestamp nel sito srand ($ sametimestamp); $ reset_password_token = rand (444444444444,999999999999); // testare il token nel sito Web Sleep (3); // per eseguire nuovamente il test con un nuovo timestamp } Posso indovinare il token? – sushi

+1

sì. Provalo. l'output di rand (444444444444,999999999999) è determinato dal valore inserito in srand. –

+0

Ci provo e non funziona. Penso che forse se generassi molti token con un timestamp con 5 minuti di anticipo forse è un lavoro? – sushi

7

tempo di attacco telaio

L'attaccante può conoscere/indovinare l'ora del vostro sistema. Ovviamente un hacker non può conoscere il secondo esatto perché per la maggior parte dei server può differire un po '.

Ma dicono per esempio il vostro tempo locale è:

> echo time(); 
1431212010 

allora si può fare una "buona congettura" che il seme sarà situato tra il 1431212005 e 1431212015.

Quindi, se si possono fare 10 ipotesi, è molto probabile che la password sia corretta.

Ovviamente l'hacker deve ancora conoscere l'algoritmo che "genera" la password. Ma per la maggior parte dei sistemi, è piuttosto semplice e, inoltre, come sempre nella sicurezza, è meglio che non si sappia molto del sistema. Dopo tutto, la maggior parte degli hacker può creare il proprio account e "ispezionare" come viene generata la password e cercare prima i modelli.

Se l'hacker ha un account lui/lei

Un modo davvero conveniente per incidere quelli della password viene inoltre inviare due richieste di reimpostazione della password a circa nello stesso momento: dire che hai un account X e si vuole incidere conto Y. Entro un millisecondo, puoi inviare due richieste, una per te e l'altra per la vittima. Successivamente si riceve la password e è possibile utilizzarla per entrambi gli account. Come dice @AlfredRossi, puoi inoltre elencare su tutti gli account del sito web e quindi hackerare la maggior parte degli account.

Solutions

La maggior parte dei sistemi offrono un modo per generare "reale casuale" (ovviamente è discutibile se si parla di vero e proprio casuale).Ad esempio catturando il rumore nei canali audio o ascoltando altri "rumori". Questi valori sono meno prevedibili poiché è difficile indovinare quale sia l'intensità misurata su un canale audio a poche migliaia di miglia dalla sua posizione.

+1

'La maggior parte dei sistemi offre un modo per generare" reale casuale "(ovviamente è discutibile se parliamo di casuale reale)' Più precisamente, [non vuoi reale casuale] (http://sockpuppet.org/blog/2014/02/25/safe-generate-random-numbers) per la crittografia. –

+0

Non sarebbe un numero intero in esecuzione, incrementato, aggiunto al timescato, contro entrambi gli attacchi? – Wortex17

+0

@ Wortex17: se l'hacker ha un account lui/lei può provare a ricostruire quel contatore. Inoltre * il contatore * di un attacco è forse una scelta di parole povere. La sicurezza non è una storia on/off, il punto è fare la minimizzazione del rischio entro limiti ragionevoli. –

13

buone soluzioni

questo presuppone è necessario un nonce a 256 bit.

  1. random_bytes(32) (PHP 7.0.0+)
  2. openssl_random_pseudo_bytes(32)
  3. mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)
  4. Lettura da /dev/urandom

Codice snippet 4 #:

<?php 
function getRandom($bytes) 
{ 
    // Read only, binary safe mode: 
    $fp = fopen('/dev/urandom', 'rb'); 

    // If we cannot open a handle, we should abort the script 
    if ($fp === false) { 
     die("File descriptor exhaustion!"); 
    } 
    // Do not buffer (and waste entropy) 
    stream_set_read_buffer($fp, 0); 

    $entropy = fread($fp, $bytes); 
    fclose($fp); 
    return $entropy; 
} 

Bad Solu zioni

  • mt_rand()
  • rand()
  • uniqid()
  • microtime(true)
  • lcg_Value()

Che cosa rende una buona soluzione?

Una buona soluzione dovrebbe sfruttare un generatore di numeri pseudocasuali crittograficamente sicuro (CSPRNG). Sui sistemi operativi basati su Unix, questo può essere ottenuto leggendo direttamente da /dev/urandom.

Ma non capisco come il token possa essere prevedibile.

Questo argomento è stato trattato in modo approfondito prima.

Ho il seguente codice:

<?php 

srand(time()); 
$reset_password_token = rand(444444444444,999999999999); 

?> 

In teoria, ci sarebbe essere solo 555555555555 valori possibili per questo. Sfortunatamente, il numero attuale è molto inferiore a.

rand() utilizza un algoritmo chiamato Linear Congruent Generator, che a causa di come è implementato in PHP 5, funziona solo con numeri interi a 32 bit senza segno. Entrambi i numeri forniti sono maggiori di 2**32. Non sono sicuro che potrebbe traboccare. The source code non è molto illuminante in questo caso.

Tuttavia, poiché si stanno seminando i numeri casuali con time(), si incontreranno dei problemi. Rapidamente, eseguire questo codice:

<?php 

srand(1431223543); 
echo rand()."\n"; 

Si dovrebbe vedere 1083759687 nella tua console. In generale, la differenza di tempo tra i computer su Internet è piuttosto piccola. Probabilmente potresti tenere conto solo di un possibile jitter fino a 2 secondi in ogni fuso orario, e ci vorranno solo 120 ipotesi (caso peggiore) per iniziare a prevedere l'output di numeri casuali. Per sempre.

Per qualsiasi motivo relativo alla sicurezza dell'applicazione, utilizzare un CSPRNG.

+0

Oltre a usare '/ dev/urandom','/dev/random' è interessante perché cerca di garantire un'alta entropia, quindi blocca le letture finché non sono disponibili abbastanza bit nel pool di entropia. –

+1

Il numero di tentativi può anche essere ridotto cercando il punto in cui si trova il server e quindi "indovina" il fuso orario. Se si fanno alcune ipotesi calcolate, probabilmente richiederà molto meno ipotesi. –

+0

@CommuSoft Ovviamente sei corretto. Realisticamente, puoi probabilmente indovinarlo in meno di 3 tentativi. Ho offerto 120 come limite superiore. –

0

Se reimpostare la mia password molte volte in un secondo, so che ottengo lo stesso token ma come un utente malintenzionato può sfruttarlo?

Hai la cosa che un aggressore deve "fare molti" di sbagliato. Un utente malintenzionato può generare i propri token per molti secondi diversi e provarli tutti contro il tuo account.