È ragionevole prevenire gli attacchi di temporizzazione utilizzando un tempo di elaborazione fisso

6

Ho sistemi che eseguono operazioni di crittografia all'interno di un tunnel SSL / TLS. La mia preoccupazione è che possa perdere informazioni sul cronometraggio durante la crittografia, la decrittografia o l'hashing.

Parte 1

  1. È una buona idea avere un tempo di elaborazione fisso (o un incremento di esso) quando si eseguono queste operazioni di crittografia?
  2. Quali operazioni dovrebbero applicare a (crittografare / decodificare o troncare)?
  3. Alcune operazioni non sono sensibili alla perdita di informazioni sui tempi? (decodifica un file, hash una password, usando PGP, RSA, AES, ecc.)

Ad esempio:

  • Durante la crittografia dei dati forniti dall'utente a una chiave privata, l'operazione totale richiederà sempre 2 secondi

  • Quando decifri un file, il thread non ritorna finché il tempo totale non ha raggiunto il multiplo di 0,5 secondi

Parte 2

  1. Se si utilizza l'approccio "multiplo di", qual è un buon valore per il multiplo? 0,5, 0,005 secondi?
posta random65537 12.02.2013 - 17:13
fonte

2 risposte

9

Il tempo di elaborazione fisso è il metodo più semplice e completo per difendersi dagli attacchi temporali: per evitare lo sfruttamento dei dati che si perdono attraverso i tempi, beh, non perdere. Tuttavia, è più facile a dirsi che a farsi. Il recente "Lucky Thirteen" mostra che è possibile rilevare le differenze temporali con una precisione al microsecondo quando l'obiettivo è "vicino" all'attaccante (sulla stessa LAN); i dettagli di attacco sfruttano la piccola perdita rimasta nelle implementazioni SSL che sono state patchate per quanto riguarda gli attacchi temporali - queste implementazioni stavano calcolando il MAC anche quando la decifrazione non produceva un padding adeguato, precisamente per ottenere un tempo di elaborazione che è stato fissato come si poteva ottenere; ma era difficile evitare una variabilità di un microsecondo.

Se imposti un tempo di elaborazione "globale" fisso (ad esempio 1 secondo per ogni richiesta), ti imbatterai in problemi con i sistemi operativi multi-tasking. Se l'implementazione è solo una chiamata sleep() dopo l'elaborazione principale, la CPU è libera di gestire altre richieste, il che sembra buono ... ma perde i dati, dal momento che l'utente malintenzionato potrebbe inviare altre richieste simultaneamente e capire se il tuo server è occupato o no. In generale, inviando molte richieste al server, l'utente malintenzionato può rendere il tempo di elaborazione per ogni richiesta arbitrariamente lungo e superare qualsiasi limite fisso. Se si limita il tempo di elaborazione a essere un multiplo integrale di una granularità fissa (ad esempio, il tempo di elaborazione è sempre n volte 0,1 secondi, con n essendo un numero intero), basta solo avere "soglie" che rendono l'operazione un po 'più difficile per l'aggressore, ma non impossibile - e potrebbe anche aiutare l'attaccante. Infatti, l'attacco "Lucky Thirteen" mostra come l'exploit di una tale soglia (corrispondente al modo in cui i dati di processo SHA-1 e SHA-256 vengono elaborati da blocchi di 64 byte) necessiti solo di un "phasing" e rende più chiara l'immagine statistica.

In questo momento, la migliore difesa sembra essere l'aggiunta di un ritardo casuale di alcuni millisecondi, che offuscherà l'immagine e impedirà l'analisi ... e, inoltre, non lasciare che l'attaccante si connetta stessa LAN del server . Che dovrebbe essere ovvio.

    
risposta data 12.02.2013 - 17:29
fonte
1

L'essenza di base di un attacco di temporizzazione è di inviare a un server diversi campioni di dati e vedere se diversi input producono percorsi di codice diversi osservando quanto tempo è stato impiegato per elaborare l'input. La migliore difesa contro gli attacchi di temporizzazione è di mantenere il codice sullo stesso percorso di esecuzione indipendentemente dall'input.

Questo è molto più facile a dirsi che a farsi. Una funzione semplice come memcmp() non garantisce lo stesso percorso di codice perché esce dopo la mancata corrispondenza del primo byte; input diversi causeranno l'uscita da punti diversi. Una risposta naturale è scrivere una funzione personalizzata memcmp() -esque, ma farlo è non avanti o .

Il problema più grande è come vengono gestiti gli errori e la convalida. Indipendentemente dagli errori di preelaborazione / convalida / sanity-check, lo stesso codice dovrebbe essere eseguito anche se ti rendi conto che l'output verrà gettato via più tardi. Quando osservi gli attacchi di temporizzazione pratica , un esempio che compare frequentemente è tempo variabile per le convalide MAC. La tempistica delle primitive crittografiche non elaborate non è davvero una preoccupazione; le operazioni di mangling bit di qualcosa come AES o SHA2 richiederanno la stessa quantità di tempo indipendentemente dalle stringhe di input che ottengono. L'obiettivo principale dovrebbe essere la gestione di errori, casi speciali e confronti tra i dati.

Una quantità fissa di tempo di muro per un'operazione non è necessariamente la migliore difesa; l'attaccante può essere in grado di aggirarlo creando l'input per rendere il tempo di operazione giusto alla soglia degli incrementi del tempo di parete costante e quindi vedere quali operazioni spingono l'operazione oltre la soglia. L'approccio ideale nella maggior parte delle situazioni è eseguire esattamente lo stesso codice indipendentemente dall'input.

Tuttavia, non conosciamo la tua situazione esatta e le informazioni esatte che stai cercando di mantenere riservate, quindi quanto sopra è generico. Ad esempio, l'approccio di mantenere l'esecuzione del codice lo stesso genererà informazioni sulla quantità di dati in elaborazione e non sappiamo se questo è un problema per te. In molti casi l'autore dell'attacco conosce già la dimensione dei dati (perché li ha forniti), ma non sappiamo se questo è un problema qui.

    
risposta data 12.02.2013 - 18:18
fonte

Leggi altre domande sui tag