Domanda

  

Poiché questa domanda è piuttosto popolare, ho pensato che fosse utile aggiornarla.

     

Vorrei sottolineare la risposta corretta come fornita da AviD a questa domanda:   

     

Non dovresti archiviare dati che devono essere crittografati nel tuo cookie. Conserva invece una chiave casuale di buone dimensioni (128 bit / 16 byte) nel cookie e memorizza le informazioni che desideri proteggere sul server, identificato dalla chiave del cookie.


Sto cercando informazioni sull'algoritmo di crittografia "migliore" per i cookie di crittografia.

Ho i seguenti requisiti:

  • Deve essere veloce
    la crittografia e la decrittografia dei dati verranno eseguite per (quasi) ogni richiesta

  • Funzionerà su piccoli set di dati, in genere stringhe di circa 100 caratteri o meno

  • Deve essere sicuro, ma non è come se stessimo proteggendo le transazioni bancarie

  • Dobbiamo essere in grado di decrittografare le informazioni in modo che SHA1 e simili siano fuori.

Ora ho letto che Blowfish è veloce e sicuro e ho letto che AES è veloce e sicuro. Con Blowfish con blocchi di dimensioni inferiori.

Penso che entrambi gli algoritmi offrano una sicurezza più che adeguata? quindi la velocità diventerebbe quindi il fattore decisivo. Ma non ho davvero idea se quegli algoritmi sono adatti per stringhe di caratteri piccoli e se ci sono forse algoritmi più adatti per la crittografia dei cookie.

Quindi la mia domanda è:
Quale algoritmo di crittografia è il migliore per crittografare i dati dei cookie?

Aggiorna
Per essere più precisi, vogliamo crittografare 2 cookie: uno con le informazioni sulla sessione e l'altro con le informazioni "ricordami".

La piattaforma è PHP come modulo apache su Linux su un VPS.

Aggiornamento 2
Sono d'accordo con cletus che la memorizzazione di qualsiasi informazione in un cookie non è sicura.

Tuttavia, abbiamo l'obbligo di implementare una funzione "remeber me". Il modo accettato per farlo è quello di impostare un cookie. Se il client presenta questo cookie, gli è consentito accedere al sistema con (quasi) uguali diritti come se avesse presentato la combinazione password utente valida.

Quindi almeno vogliamo crittografare tutti i dati nel cookie in modo che:
a) gli utenti malintenzionati non possono leggere i suoi contenuti,
b) gli utenti malintenzionati non possono fabbricare i propri cookie o manometterli.

(Tutti i dati dei cookie sono disinfettati e controllati per la validità prima di fare qualsiasi cosa con esso, ma questa è un'altra storia)

Il cookie di sessione non contiene più un sessionId / timestamp. Probabilmente potrebbe essere usato senza crittografia, ma non vedo alcun danno nel crittografarlo? (diverso dal tempo di calcolo).

Quindi, dato che dobbiamo memorizzare alcuni dati in un cookie, qual è il modo migliore per crittografarlo?

Aggiornamento 3
Le risposte a questa domanda mi hanno fatto riconsiderare l'approccio scelto. Posso davvero fare lo stesso senza la necessità di crittografia. Invece di crittografare i dati, dovrei inviare solo dati privi di significato senza il contesto e che non è possibile indovinare .

Tuttavia, sono anche in perdita:
Pensavo che la crittografia ci consentisse di inviare dati al BigBadWorld & # 8482; ed essere ancora (abbastanza) sicuro che nessuno potesse leggere o manomettere il tutto ...
Non era questo il punto cruciale della crittografia?

Ma le reazioni che seguono spingono verso: Non fidarti della crittografia per ottenere sicurezza.

Cosa mi sto perdendo ??

È stato utile?

Soluzione

Nessun vero motivo per non andare con AES con 256 bit. Assicurati di usarlo in modalità CBC e PKCS # 7 imbottitura. Come hai detto, veloce e sicuro.

Ho letto (non testato) che Blowfish potrebbe essere leggermente più veloce ... Tuttavia Blowfish ha un grande svantaggio di lunghi tempi di installazione, il che renderebbe la situazione difficile. Inoltre, AES è più "provato".

Ciò presuppone che sia veramente crittografare simmetricamente i dati dei cookie. Come altri hanno notato, in realtà non dovrebbe essere necessario e ci sono solo alcuni casi limite in cui non c'è altra scelta che farlo. Comunemente, ti conviene cambiare il design e tornare agli identificatori di sessione casuali o, se necessario, agli hash unidirezionali (usando SHA-256).
Nel tuo caso, oltre al "normale" identificatore di sessione casuale, il tuo problema è il "ricordami" " caratteristica - questo dovrebbe essere implementato anche come:

  • un numero casuale lungo, archiviato nel database e mappato su un account utente;
  • o un hash con chiave (ad es. HMAC) contenente ad es. il nome utente, il timestamp, mebbe a salt E una chiave segreta del server. Questo ovviamente può essere verificato sul lato server ...

Sembra che ci siamo allontanati un po 'dall'argomento della tua domanda originale e specifica e abbiamo cambiato la base della tua domanda cambiando il design ....
Quindi, fintanto che lo stiamo facendo, consiglierei VIVAMENTE CONTRO questa caratteristica di persistente "ricordami", per diversi motivi, il più grande tra questi:

  • Rende molto più probabile che qualcuno possa rubare la chiave di ricordo dell'utente, permettendo loro di falsificare l'identità dell'utente (e quindi probabilmente cambiare la sua password);
  • CSRF - Falsificazione richieste su più siti . La tua funzione consentirà effettivamente a un utente malintenzionato anonimo di indurre gli utenti ignari a inviare "autenticato" richieste alla tua applicazione, anche senza essere effettivamente loggato.

Altri suggerimenti

Questo tocca due questioni distinte.

In primo luogo, dirottamento della sessione . Qui è dove una terza parte scopre, per esempio, un cookie autenticato e ottiene l'accesso ai dettagli di qualcun altro.

In secondo luogo, c'è sicurezza dei dati di sessione . Con questo intendo che memorizzi i dati nel cookie (come il nome utente). Questa non è una buona idea. Qualsiasi dato di questo tipo è fondamentalmente inaffidabile, proprio come i dati dei moduli HTML non sono affidabili (indipendentemente da quale convalida Javascript e / o restrizioni di lunghezza HTML utilizzate, se presenti) perché un client è libero di inviare ciò che desidera.

Troverai spesso persone (giustamente) che invocano la sanificazione dei dati dei moduli HTML, ma i dati sui cookie verranno accettati alla cieca sul loro valore nominale. Grosso errore. In realtà, non memorizzo mai alcuna informazione nel cookie. Lo vedo come una chiave di sessione e questo è tutto.

Se si intende archiviare i dati in un cookie, si consiglia vivamente di riconsiderare.

La crittografia di questi dati non rende le informazioni più affidabili perché la crittografia simmetrica è suscettibile agli attacchi di forza bruta. Ovviamente AES-256 è migliore di, diciamo, DES (heh), ma 256 bit di sicurezza non significano necessariamente tanto quanto pensi.

Per prima cosa, i SALT sono in genere generati secondo un algoritmo o sono altrimenti suscettibili agli attacchi.

Per un altro, i dati sui cookie sono i principali candidati per gli attacchi presepe . Se si sa o si sospetta che un nome utente sia nei dati crittografati, ehi, c'è la tua culla.

Questo ci riporta al primo punto: il dirottamento.

Va ??sottolineato che negli ambienti di hosting condiviso in PHP (come esempio) i dati della sessione sono semplicemente archiviati nel filesystem ed è leggibile da chiunque altro sullo stesso host, sebbene non sappiano necessariamente quale sito esso è per. Quindi non archiviare mai password in chiaro, numeri di carte di credito, estesi dettagli personali o qualsiasi cosa che potrebbe altrimenti essere considerata sensibile nei dati di sessione in tali ambienti senza alcuna forma di crittografia o, meglio ancora, solo archiviare una chiave nella sessione e archiviare l'effettivo sensibile dati in un database.

Nota: quanto sopra non è univoco per PHP.

Ma questa è la crittografia lato server.

Ora potresti obiettare che la crittografia di una sessione con alcuni dati extra la renderà più sicura dal dirottamento. Un esempio comune è l'indirizzo IP dell'utente. Il problema è che molte persone usano lo stesso PC / laptop in molti luoghi diversi (es. Hotspot WiFi, lavoro, casa). Inoltre, molti ambienti utilizzeranno una varietà di indirizzi IP come indirizzo di origine, in particolare negli ambienti aziendali.

Potresti anche usare l'agente utente ma è indovinabile.

Quindi davvero, per quanto ne so, non c'è alcun motivo reale per usare la crittografia dei cookie. Non ho mai pensato che ci fosse, ma alla luce di questa domanda sono andato cercando di essere dimostrato giusto o sbagliato. Ho trovato alcuni thread su persone che suggeriscono modi per crittografare i dati dei cookie, farlo in modo trasparente con i moduli Apache e così via, ma questi sembrano tutti motivati ??dalla protezione dei dati memorizzati in un cookie (cosa che non dovresti fare).

Devo ancora vedere un argomento di sicurezza per crittografare un cookie che non rappresenta altro che una chiave di sessione.

Sarò felicemente smentito se qualcuno può indicare qualcosa di contrario.

  

Avviso di sicurezza : queste due funzioni non sono sicure. Stanno usando modalità ECB e non riescono a autentica il testo cifrato . Vedi questa risposta per un modo migliore di procedere.

Per coloro che leggono volendo usare questo metodo negli script PHP. Ecco un esempio funzionante che utilizza Rijndael a 256 bit (non AES).

function encrypt($text, $salt) 
{ 
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $salt, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)))); 
} 

function decrypt($text, $salt) 
{ 
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $salt, base64_decode($text), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))); 
}

Quindi per salvare il cookie

setcookie("PHPSESSION", encrypt('thecookiedata', 'longsecretsalt'));

e da leggere alla pagina seguente:

$data = decrypt(
  

Avviso di sicurezza : queste due funzioni non sono sicure. Stanno usando modalità ECB e non riescono a autentica il testo cifrato . Vedi questa risposta per un modo migliore di procedere.

Per coloro che leggono volendo usare questo metodo negli script PHP. Ecco un esempio funzionante che utilizza Rijndael a 256 bit (non AES).

function encrypt($text, $salt) 
{ 
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $salt, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)))); 
} 

function decrypt($text, $salt) 
{ 
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $salt, base64_decode($text), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))); 
}

Quindi per salvare il cookie

setcookie("PHPSESSION", encrypt('thecookiedata', 'longsecretsalt'));

e da leggere alla pagina seguente:

<*>COOKIE['PHPSESSION'], 'longsecretsalt');

Puoi ottenere ciò che desideri in modo sicuro utilizzando AES in modalità EAX. Il testo cifrato sarà più grande del testo normale; è normale per la crittografia sicura.

L'attaccante conoscerà ovviamente la lunghezza del tuo testo in chiaro dal testo cifrato, ma non dovrebbero essere in grado di determinare nient'altro.

Genera chiavi AES in modo casuale.

Assicurati di utilizzare un nuovo nonce per ogni crittografia e usa i "dati associati" campo per garantire che una cosa che hai crittografato per uno scopo non sia presentata come per un altro (quindi cose come il nome utente e il nome del cookie potrebbero andare lì)

  

le reazioni seguenti spingono verso: Do   non fidarsi della crittografia da realizzare   la sicurezza.

Altro "se non sei un esperto di crittografia, sottovaluterai quanto sia facile sbagliare". Ad esempio, AFAICT nessun altro in questo thread ha discusso delle modalità di concatenamento o dell'integrità del messaggio, che copre due errori comuni del principiante.

Cookie veloci e crittografati con Libsodium

Se hai bisogno di cookie criptati veloci e sicuri in PHP, controlla come Halite li implementa. Halite si affida a l'estensione PECL libsodium per fornire una crittografia sicura.

<?php
use \ParagonIE\Halite\Cookie;
use \ParagonIE\Halite\Symmetric\Key;
use \ParagonIE\Halite\Symmetric\SecretKey;

// You can also use Key::deriveFromPassword($password, $salt, Key::CRYPTO_SECRETBOX);
$encryption_key = new SecretKey($some_constant_32byte_string_here);

$cookie = new Cookie($encryption_key);

$cookie->store('index', $any_value);
$some_value = $cookie->fetch('other_index');

Se non puoi installare estensioni PECL, chiedi al tuo amministratore di sistema o al provider di hosting di farlo per te. Se rifiutano, hai ancora delle opzioni.


Proteggi i cookie crittografati in PHP, tieni il sale per favore

Le altre risposte ti chiedono di crittografare i tuoi dati con openssl o mcrypt, ma manca un passaggio cruciale. Se vuoi crittografare in modo sicuro i dati in PHP , devi autenticare i tuoi messaggi.

Usando l'estensione OpenSSL, il processo che dovresti seguire è simile al seguente:


Preambolo

  • (Prima ancora di pensare alla crittografia) Genera una stringa casuale a 128 bit, 192-bit o 256-bit. Questa sarà la tua chiave principale .

    Non utilizzare una password leggibile dall'uomo. Se, per qualche motivo, devi utilizzare una password leggibile dall'uomo, chiedi Crittografia SE come guida.

    Se hai bisogno di un'attenzione speciale, il mio datore di lavoro offre servizi di consulenza tecnologica , incluso lo sviluppo della crittografia caratteristiche.

crittografia

  1. Genera un vettore di inizializzazione casuale (IV) o nonce. per esempio. random_bytes (openssl_cipher_iv_length ( 'AES-256-CBC'))
  2. Usa hash_equals () .
  3. Se e solo se il passaggio 3 viene superato, decrittografare il testo cifrato utilizzando $ eKey .

Se vuoi vedere come appare tutto insieme, vedi questa risposta che ha un codice di esempio .

Se sembra troppo lavoro, usa defuse / php-crittografia o zend-crypt e chiamalo un giorno.


Cookie Remember Me

  

Tuttavia, abbiamo l'obbligo di implementare una funzione "remeber me". Il modo accettato per farlo è quello di impostare un cookie. Se il client presenta questo cookie, gli è consentito accedere al sistema con (quasi) uguali diritti come se avesse presentato la combinazione password utente valida.

La crittografia non è in realtà lo strumento corretto per questo lavoro. Vuoi seguire questo processo per sicuro ricordami cookie in PHP :

Generazione di un token Remember Me

  1. Genera due stringhe casuali:
    1. Un selettore che verrà utilizzato per le ricerche nel database. (Lo scopo di un selettore casuale anziché solo di un ID sequenziale è quello di non perdere quanti utenti attivi ci sono sul tuo sito Web. Se ti trovi a perdere queste informazioni, sentiti libero di usare solo un ID sequenziale .)
    2. Un validatore che verrà utilizzato per autenticare l'utente automaticamente.
  2. Calcola un hash di validator (basterà un semplice hash SHA-256).
  3. Memorizza il selettore e l'hash del validator in una tabella del database riservata agli accessi automatici.
  4. Memorizza il selettore e validator in un cookie sul client.

Riscattare un token Remember Me

  1. Dividi il cookie in arrivo nel selettore e validator .
  2. Esegui una ricerca nel database (usa dichiarazioni preparate !) in base al selettore .
  3. Se viene trovata una riga, calcola un hash del validator .
  4. Confronta l'hash calcolato al passaggio 3 con l'hash memorizzato nel database, usando nuovamente hash_equals ( ) .
  5. Se il passaggio 4 restituisce true, accedere all'utente all'account appropriato.

Questa è la strategia che Gatekeeper ha adottato per l'autenticazione a lungo termine dell'utente ed è la più sicura strategia proposta finora per soddisfare questo requisito.

Mentre entrambi sono molto forti, AES è uno standard.

Per quanto riguarda la sicurezza di piccoli blocchi di dati: più piccolo è, meglio è. Meno dati crittografati sono esposti, più a lungo è possibile utilizzare la chiave. Esiste sempre un limite teorico alla quantità di dati che possono essere crittografati all'interno di una chiave di un determinato algoritmo senza esporre il sistema a rischi.

Se si crittografa il cookie, il server deve ancora decodificarlo per leggerlo (per verificare la stessa chiave), quindi qualsiasi cookie crittografato è inutile, perché se rubato (e non modificato) porterà comunque l'hacker a destra al tuo account. È pericoloso come non crittografato.

Credo che il vero problema di qualcuno che ruba il tuo cookie sia la connessione tra il server e il client. Usa la connessione SSL fornita dal tuo host.

Per quanto riguarda il tuo cookie, devi creare un lungo ID casuale per utente nel database (modificalo ad ogni accesso) e impostalo come cookie o sessione. Il cookie che contiene la chiave può essere verificato tramite php e se è uguale a un account o una tabella nel database, scaricare i dati sulla pagina Web come di consueto.

Come sottolineato più volte nei commenti precedenti, devi applicare protezione dell'integrità a qualsiasi testo cifrato che invii all'utente e che accetti nuovamente. Altrimenti è possibile modificare i dati protetti o recuperare la chiave di crittografia.

Soprattutto il mondo PHP è pieno di cattivi esempi che lo ignorano (vedi Crittografia PHP - procedi con cura ) ma questo vale per qualsiasi lingua.

Uno dei pochi esempi che ho visto è PHP-CryptLib che utilizza la crittografia combinata- modalità di autenticazione per fare il lavoro. Per Python pyOCB offre funzionalità simili.

Perché vuoi crittografare il cookie?

A mio modo di vedere, ci sono due casi: o dai la chiave al cliente, oppure no.

Se non dai la chiave al cliente, perché dai loro i dati? A meno che tu non stia giocando a un gioco strano con la rottura della crittografia debole (cosa che non sei esplicitamente no), potresti anche archiviare i dati sul server.

Se fai consegna la chiave al client, allora perché la crittografi in primo luogo? Se non crittografare la comunicazione della chiave, la crittografia del cookie è controversa: un MITM può guardare il cookie e inviarti qualsiasi cookie che desidera. Se si utilizza un canale crittografato per il client, perché l'overhead aggiuntivo della crittografia dei dati memorizzati?

Se sei preoccupato che altri utenti sul computer del client leggano il cookie, rinuncia e presumi che il browser imposti i bit di autorizzazione :)

AES (noto anche come Rijndael) è il più popolare. La dimensione del blocco è di 128 bit, ovvero solo 16 byte, e stai parlando di "circa 100 caratteri".

Penso che " dare via " tutti i dati anche crittografati quando si tratta di nome utente e password non sono buoni ... Ci sono molti JS che possono annusarlo ... Ti suggerisco di creare nella tabella DB degli utenti un campo cookie_auth o qualunque cosa ...

dopo la prima raccolta di login: attuale: browser, IP, e qualche chiave salata, più il tuo hostname var ...

crea un hash e archivia in quel campo ... imposta un cookie ... quando il cookie " risponde " confronta tutti questi con l'hash memorizzato e fatto ...

anche se qualcuno "ruba" un cookie che non saranno in grado di usarlo :-)

Spero che questo aiuti :-)

FEHA vision.to

Inoltre, ho provato mcrypt_encrypt e una cosa, tieni a mente. Se si esegue base64_encode (mcrypt_encrypt (...)) .

e successivamente, si esegue base64_decode e si producono i dati crittografati ( echo ). Probabilmente sarai fregato e non vedrai nulla. Tuttavia, se si esegue mcrypt_decrypt (... base64_decode ($ value)) . Vedrai i dati originali.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top