Ho scritto a lungo su sicuro caselle di accesso e "ricordami" . La risposta accettata non è sbagliata, ma direi che è un po 'più complicato da un punto di vista rispetto a quello che deve essere, e trascura un'area in cui è necessaria un po' più di complessità.
generate and store a nonce on the server side, hash that with the username and other info (e.g. client ip, computername, timestamp, similar stuff), and send that in the cookie. The nonce should be stored in the database, together with expiry date, and both checked when the cookie comes back.
Quindi un'implementazione che non espone alcuna informazione al client potrebbe sembrare ...
// Storage:
setcookie(
'rememberme',
hash_hmac('sha256', $username . $_SERVER['REMOTE_ADDR'], $storedNonce),
time() + 8640000 // 100 days, for example
);
// Validation:
$valid = hash_equals(
$_COOKIE['rememberme'],
hash_hmac('sha256', $username . $_SERVER['REMOTE_ADDR'], $storedNonce)
);
La ovvia limitazione qui è che, se il tuo indirizzo IP (o altre informazioni) cambia, il tuo cookie è inutile. Alcuni potrebbero vedere questo come una buona cosa, lo vedo come inutilmente ostile verso l'usabilità per gli utenti Tor.
Puoi certamente interpretare la citazione sopra per indicare qualcosa di diverso, come il token Web JSON di un povero uomo. Tuttavia, i cookie HTTP sono limitati a 4 KiB per dominio. Lo spazio è prezioso.
Un altro problema: quante informazioni perde la query del database sulla tua applicazione? (Sì, sto parlando di canali secondari.)
Strategia "Remember Me" sicura di Paragon Initiative
Conservazione:
- Genera una stringa casuale da 9 byte da
random_bytes()
(PHP 7.0+ o tramite random_compat ), base64 lo codifica su 12. Questo sarà usato per ricerche nel database.
- Genera un'altra stringa casuale, preferibilmente lunga almeno 18 byte, e ancora una volta base64 la codifica (a 24+). Questo verrà effettivamente utilizzato per l'autenticazione.
- Memorizza
$lookup
e hash('sha256, $validator)
nel database; ovviamente associato a un account utente specifico.
- Memorizza
$lookup . $validator
nel cookie HTTP dell'utente (ad esempio rememberme
).
Convalida (accesso automatico):
- Dividi il cookie in
$lookup
e $validator
.
- Esegui una ricerca nel database basata su
$lookup
; va bene se c'è un canale laterale temporizzato qui.
- Controlla
hash_equals($row['hashedValdator'], hash('sha256', $validator))
.
- Se il passaggio 3 restituisce
TRUE
, associare la sessione corrente con l'account utente appropriato.
Analisi della sicurezza:
-
Quali canali secondari sono mitigati?
Il più significativo: attenua l'impatto delle perdite di informazioni temporali sull'operazione di confronto delle stringhe utilizzata nella ricerca del database.
Se hai implementato un'autentica autenticazione token casuale, un utente malintenzionato potrebbe inviare molte richieste finché non troveranno un token di autenticazione valido per un utente. (Probabilmente non sarebbero in grado di selezionare la vittima che stanno impersonando.)
-
Che cosa succede se un utente malintenzionato può divulgare la tabella del database di autenticazione a lungo termine?
Abbiamo archiviato un hash SHA256 di
$validator
nel database, ma il testo in chiaro per l'hash è memorizzato nel cookie. Poiché l'input è un valore di entropia elevato, è improbabile che la ricerca di forza bruta produca risultati. (Questo riduce anche la necessità di ad esempio bcrypt.)
Questa strategia è implementata in Gatekeeper .