Tutorials

5. Attacchi e Modalità Avanzate AES

Questo documento approfondisce le vulnerabilità specifiche della modalità AES-CBC e introduce il concetto di Crittografia Autenticata AE e Crittografia Autenticata con Dati Associati AEAD, con un focu

Questo documento approfondisce le vulnerabilità specifiche della modalità AES-CBC e introduce il concetto di Crittografia Autenticata (AE) e Crittografia Autenticata con Dati Associati (AEAD), con un focus su AES-GCM.


1. Attacco Chosen Plaintext ad AES-CBC

La modalità CBC (Cipher Block Chaining) è vulnerabile a specifici attacchi di tipo Chosen Plaintext Attack se si verificano due condizioni: 1. Il Vettore di Inizializzazione (IV) è predicibile a priori. 2. Il Vettore di Inizializzazione (IV) non è riservato ed è allegato in chiaro al messaggio.

Se queste condizioni sono soddisfatte, l'attaccante ha la possibilità di scegliere il plaintext sapendo quale IV verrà utilizzato.

Meccanismo dell'Attacco:

Consideriamo: $vP$, $vC$, $vIV$: Plaintext da decifrare, il suo ciphertext e il relativo IV. $aP$, $aC$, $aIV$: Chosen Plaintext (scelto dall'attaccante), il suo ciphertext risultante e l'IV utilizzato (noto in anticipo dall'attaccante).

L'attaccante può forgiare un plaintext ($aP$) per un blocco specifico (es. il primo blocco, $aP[1]$) nel seguente modo: $aP[1] = vIV \oplus aIV \oplus B$ Dove $B$ è un blocco che l'attaccante "brute-forza".

Generando un ciphertext il cui primo blocco è dato da: $aC[1] = E(K, aP[1] \oplus aIV)$ Sostituendo $aP[1]$: $aC[1] = E(K, (vIV \oplus aIV \oplus B) \oplus aIV)$ Per le proprietà dello XOR ($X \oplus X = 0$): $aC[1] = E(K, vIV \oplus B)$

Pertanto, se $aC[1]$ (il blocco cifrato dall'attaccante) è uguale a $vC[1]$ (il blocco cifrato vittima), allora ne consegue che $vP[1] = B$. L'attaccante continua a variare $B$ (eseguendo un "brute force block") fino a quando non trova una corrispondenza.

Costo dell'Attacco:

Brute-forzare un singolo blocco richiede al massimo $2^{128}$ tentativi (per blocchi AES da 128 bit). Questo attacco è vantaggioso rispetto a un attacco sulla chiave in due situazioni: 1. Quando AES è utilizzato con chiavi > 128 bit (es. AES-192, AES-256), dove la ricerca della chiave sarebbe più onerosa. 2. Quando l'attaccante possiede informazioni aggiuntive sul plaintext (es. è un testo, un formato specifico), che possono diminuire drasticamente il numero di tentativi necessari per $B$.

Caso Reale: Attacco BEAST (Browser Exploit Against SSL/TLS)

TLS 1.0 utilizzava AES in modalità CBC e, come vettore di inizializzazione, impiegava l'ultimo blocco del ciphertext precedente. Questa predittibilità dell'IV, combinata con altre tecniche, ha reso possibile la decodifica di alcuni ciphertext in attacchi come il BEAST (Browser Exploit Against SSL/TLS).


2. Attacco Padding Oracle ad AES-CBC

Il Padding Oracle Attack è un attacco che mira a decifrare un messaggio sfruttando il modo in cui viene gestito l'algoritmo di padding.

Padding PKCS7:

AES effettua il padding utilizzando l'algoritmo PKCS7, che prevede di riempire i byte mancanti in un blocco come segue: Se deve essere inserito un solo byte: 0x01 Se devono essere inseriti due byte: 0x02 0x02 Se devono essere inseriti $N$ byte: $N$ volte il valore $N$ (es. per 15 byte: 0x0F ripetuto 15 volte). Se il plaintext non necessita di padding (è già un multiplo della dimensione del blocco): vengono inseriti 16 byte con valore 0x10. PKCS7 permette di identificare facilmente i byte di padding, evitando di confonderli con i byte del plaintext effettivo.

Condizione per l'Attacco:

Per poter attuare un Padding Oracle Attack, è necessaria una sola condizione: Disponibilità di un sistema (oracolo) che risponde comunicando la correttezza/non correttezza del padding. L'oracolo riceve un ciphertext, lo decifra, verifica la correttezza del padding del plaintext e ne comunica l'esito. Esempio: Un endpoint di una Web API che riceve un ciphertext e restituisce 200 OK se il padding è corretto e 500 Error se non lo è.

Meccanismo dell'Attacco:

L'attaccante può modificare arbitrariamente i byte del penultimo blocco del ciphertext (C1') generando modifiche nell'ultimo blocco del plaintext (P2'), che è quello sottoposto alla verifica del padding.

Supponiamo di voler decifrare un ciphertext composto da due blocchi: C1 + C2.

Obiettivo: Decifrare $P_2$ (il plaintext corrispondente a $C_2$). Sappiamo che in CBC: $P_i = C_{i-1} \oplus D(K, C_i)$. Quindi, per $P_2$: $P_2 = C_1 \oplus D(K, C_2)$. Definiamo un blocco intermedio $I_2 = D(K, C_2)$. Allora $P_2 = C_1 \oplus I_2$.

L'attaccante non conosce $I_2$. Procede per tentativi sull'ultimo byte (e poi sugli altri) del blocco che precede quello che vuole decifrare.

Fasi per decifrare $P_2$[16] (l'ultimo byte del blocco $P_2$): 1. L'attaccante crea un blocco $C_1'$ arbitrario e lo invia all'oracolo concatenato a $C_2$: $C_1' + C_2$. 2. L'oracolo decifra $C_1' + C_2$ ottenendo $P_1' + P_2'$. In particolare, $P_2' = C_1' \oplus D(K, C_2) = C_1' \oplus I_2$. 3. L'attaccante varia il sedicesimo byte di $C_1'$ ($C_1'[16]$) da 0x00 a 0xFF, provando tutte le 256 possibilità, finché l'oracolo non risponde con "padding corretto". 4. Quando l'oracolo risponde positivamente, significa che $P_2'$ (il blocco decifrato) termina con 0x01 (padding di 1 byte). Quindi $P_2'[16] = 0x01$. Poiché $P_2'[16] = C_1'[16] \oplus I_2[16]$, possiamo ricavare $I_2[16] = C_1'[16] \oplus P_2'[16] = C_1'[16] \oplus 0x01$. Avendo $I_2[16]$, si può ricavare il byte originale $P_2[16] = C_1[16] \oplus I_2[16]$.

Fasi per decifrare $P_2$[15] (il quindicesimo byte del blocco $P_2$): 1. L'attaccante imposta $P_2'[16]$ a 0x02 (padding di 2 byte) modificando opportunamente $C_1'[16]$ (cioè $C_1'[16] = I_2[16] \oplus 0x02$). 2. Si varia $C_1'[15]$ da 0x00 a 0xFF finché l'oracolo non risponde con "padding corretto", indicando che $P_2'[15]$ e $P_2'[16]$ valgono entrambi 0x02. 3. Quindi $P_2'[15] = 0x02$. 4. Si ricava $I_2[15] = C_1'[15] \oplus P_2'[15] = C_1'[15] \oplus 0x02$. 5. Avendo $I_2[15]$, si ricava il byte originale $P_2[15] = C_1[15] \oplus I_2[15]$.

L'attacco prosegue byte per byte per l'intero blocco. Successivamente, si procede con le medesime modalità per tutti i blocchi precedenti. Per la decodifica del primo blocco, è necessaria la conoscenza del Vettore di Inizializzazione (IV), poiché $P_1[n] = IV[n] \oplus I_1[n]$. Non sarà possibile decodificare il primo blocco se l'IV è cifrato o sconosciuto all'attaccante. L'identificazione di ogni singolo byte richiede, al massimo, 255 interpellazioni dell'oracolo.


3. Crittografia Autenticata (AE)

L'Authenticated Encryption (AE) mira a ottenere simultaneamente riservatezza e autenticità dei messaggi, risolvendo problemi derivanti da modifiche al ciphertext e implementando protocolli che garantiscano entrambe le proprietà. AE si ottiene combinando un algoritmo di autenticazione e un algoritmo di cifratura. Esistono quattro approcci principali:

1. Hash seguito da Encryption (H $\rightarrow$ E): Si calcola prima l'hash del messaggio, e poi si cifrano sia il messaggio che l'hash. Formula: $E(K, m || H(m))$ 2. Autenticazione seguita da Encryption (A $\rightarrow$ E): Si usa un algoritmo di MAC (Message Authentication Code) per autenticare il plaintext, e poi si cifrano il MAC e il messaggio. Vengono usate due chiavi (una per il MAC, una per la cifratura). Approccio usato in TLS/SSL. Formula: $E(K_2, m || MAC(K_1, m))$ 3. Encryption seguita da Autenticazione (E $\rightarrow$ A): Il messaggio viene cifrato, e il ciphertext risultante viene autenticato con un algoritmo di MAC. Anche in questo caso, vengono usate due chiavi. Approccio usato in IPSec. Formula: $MAC(K_2, E(K_1, m))$ 4. Autenticazione ed Encryption Indipendenti (E + A): Le due fasi sono indipendenti e avvengono entrambe sul plaintext con due chiavi differenti. Approccio usato da SSH. Formula: $E(K_1, m) || MAC(K_2, m)$

Tutti questi approcci sono facilmente reversibili.


4. Crittografia Autenticata con Dati Associati (AEAD)

Ci sono situazioni in cui è necessario autenticare dati che devono però rimanere in chiaro (es. un indirizzo IP), preservandone l'integrità senza cifrarli. La modalità AEAD (Authenticated Encryption with Associated Data) affronta questa necessità, permettendo di avere un ciphertext, dei dati in chiaro e un'autenticazione che copre sia i dati cifrati che quelli in chiaro.


5. AES-GCM (Galois/Counter Mode)

GCM è una modalità operativa AEAD, standard NIST e disponibile su AES.

Utilizza una semplice variante di CTR (Counter Mode) per l'encryption. In GCTR, i contatori sono calcolati con incrementi fissi a partire da un contatore iniziale, non direttamente usato per la cifratura del plaintext. Utilizza GHASH (una funzione di hash con chiave) per l'autenticazione.

Funzionamento di GCM:

Encryption (GCTR): I contatori sono calcolati con incrementi fissi (es. $Counter_0, Counter_0+1, Counter_0+2, ...$). Ogni valore del contatore viene cifrato con la chiave, e il risultato viene XORato con il blocco di plaintext per produrre il ciphertext. Authentication (GHASH): La funzione di compressione GHASH effettua una moltiplicazione algebrica nei campi di Galois (campi finiti) tra la chiave $H$ (derivata dalla chiave principale) e lo XOR calcolato tra il blocco corrente e il blocco precedente. Il blocco è di 128 bit, così come l'output. Il vettore di inizializzazione per GHASH è composto da tutti zeri.

Schema Generale di GCM:

Gli input per GCM sono: Plaintext IV (Vettore di Inizializzazione) Associated Data (dati da autenticare ma non cifrare) Chiave di Cifratura

Associated Data e Ciphertext sono sottoposti a padding per raggiungere multipli di 128 bit. Le lunghezze dell'Associated Data (len(A)) e del Ciphertext (len(C)) sono entrambe espresse con 64 bit e incluse nel calcolo del TAG di autenticazione finale.

Vantaggi di AES-GCM:

La parte di encryption è ben separata dalla parte di authentication. L'encryption è parallelizzabile grazie alle caratteristiche proprie di CTR. La parte di authentication è sequenziale, ma può lavorare in parallelo rispetto all'encryption. Le moltiplicazioni in campo finito sono facili da implementare in hardware e sono disponibili nelle principali architetture moderne, rendendo GCM molto efficiente.


Spero che questi appunti dettagliati ti siano d'aiuto per il tuo corso! Hai altre domande o desideri approfondire qualche aspetto?