Non capita tutti i giorni di poter applicare le lezioni della crittoanalisi della Seconda Guerra Mondiale alle proprie applicazioni web. Ma oggi è esattamente quello che faremo. Infatti, vedremo come anche uno dei più potenti strumenti crittografici moderni possa essere sconfitto con lo stesso metodo utilizzato da Alan Turing per decifrare la macchina Enigma, che era il più potente strumento crittografico dell'epoca, se gli implementatori commettono gli stessi errori di trasmissione dei messaggi riscontrati da Turing.
Diamo un'occhiata a un'API che ho valutato di recente, per vedere come ha evitato il problema che ha aiutato gli Alleati a battere le potenze dell'Asse nella Seconda Guerra Mondiale.
Un'API per il commercio elettronico: Un dolce vasetto di miele
L'esempio che analizzerò oggi è l'API di un'azienda di e-commerce per l'accettazione dei pagamenti. Per quanto riguarda gli obiettivi di attacco, non ci sono molti obiettivi più preziosi di un'API per i pagamenti con carta di credito. Ecco perché questa azienda ha deciso di esporre al mondo una chiave pubblica con cui gli utenti dell'API possono crittografare tutte le informazioni della carta di credito inviate per l'elaborazione del pagamento.
Esatto, tutti i dati inviati da questo modulo saranno crittografati e mai inviati in chiaro. Questo perché è importante proteggere tutti i dati da eventuali attacchi, non solo il numero della carta. La data di scadenza e il CVV fanno parte del pacchetto che rende unico un particolare metodo di pagamento, quindi l'azienda li ha crittografati. L'azienda non avrebbe mai inviato alcun dato in chiaro.
Ecco come appariva una richiesta campione mentre attraversava il filo, utilizzando un Charles Proxy per catturare il traffico come man-in-the-middle:
In questo esempio si notano due valori hash: paymentHash e cvvHash. Pensiamo ai dati contenuti in questi due valori.
Per paymentHash, abbiamo il numero di carta di credito a 16 cifre, crittografato utilizzando la chiave pubblica pubblicata per l'uso su questa API. Ovviamente, i valori disponibili per la crittografia saranno molto diversi.
Per cvvHash, la situazione non è affatto la stessa! I CVV sono composti da sole 3 cifre. Se si crittografano solo combinazioni di tre cifre, un utente malintenzionato potrebbe costruire un dizionario completo di soli 1.000 valori diversi (10 valori per ciascuna delle 3 cifre). Con questo dizionario, potrebbe trovare il CVV di qualsiasi carta inviata attraverso l'API. Fortunatamente, il mio cliente sapeva come evitare gli attacchi noti al testo in chiaro e aveva già implementato un padding randomizzato per evitare lo stesso attacco che ha fatto cadere i nazisti.
Decifrare l'enigma
In parte, la macchina Enigma era così difficile da decifrare perché aveva una struttura molto complessa per la crittografia dei messaggi e le impostazioni venivano modificate di frequente. Tuttavia, poiché la macchina veniva utilizzata per i messaggi militari, il team di Turing a Bletchley Park iniziò a cercare un testo che poteva essere previsto in molti messaggi.
Un tipo di messaggio frequentemente inviato dall'esercito tedesco era il bollettino meteorologico, che includeva la parola tedesca per "tempo" nello stesso punto di ogni messaggio, seguita dalle condizioni meteorologiche note. Un altro esempio è che molti messaggi terminavano con "Heil Hitler" e alcuni operatori usavano saluti standard. Questi casi hanno anche permesso di determinare alcuni dei testi in chiaro e delle impostazioni per ogni giorno.
Questo tipo di vulnerabilità di crittografia si sarebbe potuta presentare se l'azienda di e-commerce non avesse utilizzato un padding randomizzato per il CVV, poiché il numero di valori possibili è molto ridotto.
Evitare lo stesso errore
Utilizzando un pad casuale, l'azienda ha garantito che due metodi di pagamento con lo stesso CVV non rivelassero nulla di ciò che veniva trasmesso. Ecco alcuni esempi di come lo stesso valore di "777" possa essere crittografato per avere valori diversi utilizzando un pad:
$ echo -n 777 | openssl rsautl -inkey public_key.pem -pubin -pkcs |
Come si può notare, i comandi eseguiti sopra sono tutti uguali, ma a causa degli standard della crittografia RSA, i valori in uscita sono completamente diversi.
Buoni algoritmi di crittografia non sono sufficienti
Questo esempio dovrebbe aiutarvi a capire che non basta mettere in atto un buon schema di crittografia. Anche con algoritmi di crittografia molto sofisticati, se viene utilizzato più volte lo stesso input, è possibile che questo riveli i dati che si sta cercando di trasmettere in modo sicuro. È molto importante, soprattutto quando si tratta di informazioni di pagamento, assicurarsi che non sia facile indovinare i valori inviati attraverso il filo.
Un altro esempio in cui il padding è importante è la memorizzazione delle password. Gli sviluppatori sanno di dover utilizzare una buona funzione di hash unidirezionale per assicurarsi di non poter leggere le password inviate dagli utenti. A tal fine, gli sviluppatori dovrebbero aggiungere una stringa casuale (chiamata salt ) a qualsiasi password prima di eseguire l'hash.
Conclusione
La sicurezza delle applicazioni web è un compito estremamente importante. Assicurarsi che i dati sensibili dei vostri utenti non siano facilmente decifrabili crea fiducia nei clienti e garantisce la longevità della vostra azienda. Dopo tutto, nessuno vuole che i media dicano che il proprio sito ha fatto trapelare le informazioni di pagamento dei clienti. Se riuscite a fare in modo di non criptare sempre gli stessi valori, eviterete un errore molto elementare e terrete al sicuro i dati dei vostri clienti.
Per ulteriori informazioni sulle migliori pratiche di sicurezza, consultare l'ampia serie di guide alla sicurezza di Linode!
Commenti