Terminologia critica che gli sviluppatori devono conoscere

Nell’era digitale, dove i dati giocano un ruolo sempre più centrale, la protezione delle informazioni personali degli utenti è diventata una priorità assoluta.

Noi sviluppatori, già alle prese con sistemi complessi e vulnerabili, caratterizzati da molteplici punti di potenziale errore, dobbiamo tradurre le esigenze degli utenti in interfacce funzionali e backend efficienti. A tutto ciò si aggiunge ora un’ulteriore, fondamentale sfida: la sicurezza dei dati. Questo imperativo nasce sia dalla necessità di tutelare i nostri clienti, che giustamente si sentono traditi quando i loro dati vengono utilizzati in modo improprio, sia dalle stringenti normative imposte da governi e aziende.

La sicurezza dei dati: una responsabilità condivisa

La complessità della sicurezza risiede nella sua natura multi-livello, che la rende una responsabilità di tutti, ma allo stesso tempo, di nessuno in particolare. Nei moderni team che operano nel cloud, diversi gruppi sono coinvolti nella gestione dei dati: sviluppatori, amministratori di database, amministratori di sistema (o specialisti DevOps), e utenti back-office con privilegi. Ciascuno di questi ruoli, preso dalla gestione del proprio ambito di competenza, può erroneamente percepire la sicurezza dei dati come una preoccupazione altrui. La realtà è che ogni figura professionale ha le sue specificità: un amministratore di database non può controllare la sicurezza lato applicazione, così come un DevOps non ha il controllo sugli accessi al back-office.

Il ruolo cruciale degli sviluppatori nella sicurezza dei dati

Nonostante questa frammentazione, gli sviluppatori si trovano a gestire la superficie di accesso ai dati più ampia. Sono loro a costruire ogni componente dell’applicazione, a collegarsi a diversi servizi backend, a gestire i token di accesso e ad avere pieno controllo sul cluster di database. Le applicazioni, infatti, hanno un accesso illimitato a tutte le parti del sistema: un’applicazione Django in produzione, ad esempio, ha la facoltà di scaricare o cancellare l’intero archivio S3 degli ultimi dieci anni. Pertanto, è proprio a livello del codice sorgente che si presenta la maggiore possibilità di negligenza o disattenzione, e la responsabilità ricade direttamente sullo sviluppatore.

La sicurezza dei dati è un argomento vastissimo e non è possibile trattarlo esaustivamente in un singolo articolo. Tuttavia, intendo presentare la terminologia essenziale che ogni sviluppatore deve conoscere per proteggere adeguatamente le proprie applicazioni. Consideratelo un “Corso Base sulla Sicurezza dei Dati per App”.

Iniziamo!

Hashing

Se desideriamo una definizione rigorosa, possiamo sempre consultare Wikipedia. In termini più semplici, l’hashing è il processo di trasformazione dei dati in una forma non leggibile. Ad esempio, utilizzando la nota (e poco sicura) codifica Base64, la frase “Il mio segreto è al sicuro con te?” può essere “hashata” in “SXMgbXkgc2VjcmV0IHNhZmUgd2l0aCB5b3U/”. Se, ad esempio, teneste un diario in formato Base64, i vostri familiari non potrebbero leggerlo (a meno che non sappiano come decodificare da Base64!).

Questa tecnica di codifica dei dati è utilizzata per archiviare password, numeri di carte di credito e altre informazioni sensibili nelle applicazioni web (e in realtà dovrebbe essere applicata in tutti i tipi di app). L’obiettivo è, ovviamente, che in caso di violazione dei dati, un aggressore non possa utilizzare queste informazioni per causare danni concreti. Per eseguire l’hashing, si utilizzano algoritmi robusti e sofisticati; un metodo come Base64 sarebbe facilmente violato da un qualsiasi malintenzionato.

L’hashing delle password utilizza una tecnica crittografica chiamata hashing unidirezionale, il che significa che, sebbene sia possibile codificare i dati, non è possibile decodificarli. Come fa, allora, l’applicazione a sapere che la password inserita è corretta? Semplicemente, utilizza lo stesso processo per confrontare la forma crittografata della password appena inserita con quella memorizzata nel database. Se corrispondono, l’accesso viene consentito!

Parlando di hash, ecco un’informazione interessante. Se scaricate software o file da internet, potrebbe esservi stato chiesto di verificarli prima di utilizzarli. Ad esempio, se scaricate l’ISO di Ubuntu Linux, la pagina di download vi offrirà la possibilità di verificare il download. Cliccandoci sopra, si aprirà una finestra:

La finestra indica di eseguire un comando, che calcolerà l’hash dell’intero file scaricato e lo confronterà con la stringa hash visualizzata sulla pagina di download: 5fdebc435ded46ae99136ca875afc6f05bde217be7dd018e1841924f71db46b5. Questa conversione viene eseguita utilizzando l’algoritmo SHA256, come indicato dalle ultime parole del comando: shasum -a 256 –check.

L’idea è che se l’hash prodotto dal vostro controllo è diverso, significa che qualcuno ha manomesso il download e vi ha fornito un file compromesso.

Tra gli algoritmi più comuni nell’ambito dell’hashing delle password troviamo MD5 (ormai considerato insicuro), SHA-1 e SHA-2 (famiglia di algoritmi di cui SHA-256 e SHA-512 fanno parte), SCRYPT, BCRYPT, eccetera.

Salatura (Salting)

La sicurezza è una continua lotta tra “guardie e ladri”: i malintenzionati studiano i sistemi esistenti per trovare nuove falle, e i “creatori di serrature” rispondono rafforzando le difese. La crittografia non fa eccezione. Nonostante l’hashing renda impossibile risalire alla password originale, gli aggressori hanno sviluppato sofisticate tecniche che combinano logica e potenza di calcolo; per questo, in molti casi riescono a prevedere la password corretta partendo dal suo hash.

“Signor Rumpelstiltskin, suppongo?!”

Per ovviare a questo problema, si è sviluppata la tecnica del “salting”. In pratica, l’hash della password (o di qualsiasi altro dato) viene calcolato sulla base di due elementi: i dati originali e una stringa casuale generata appositamente per ogni utente (il “salt”), che l’attaccante non può prevedere. Quindi, con il “salting”, se vogliamo hashare la password “superman009”, dobbiamo prima selezionare una stringa casuale come “bCQC6Z2LlbAsqj77”, e poi calcolare l’hash di “superman009-bCQC6Z2LlbAsqj77”. L’hash risultante sarà diverso da quelli tipici prodotti dall’algoritmo, rendendo più difficile il reverse engineering o le congetture intelligenti.

Sia l’hashing che il salting sono ambiti estremamente complessi e in continua evoluzione. Come sviluppatori, non ci troveremo mai a gestirli direttamente, ma una buona conoscenza di questi concetti ci aiuta a prendere decisioni più consapevoli. Ad esempio, se state lavorando su un vecchio framework PHP e notate che usa hash MD5 per le password, sapete che è il momento di integrare una libreria più sicura per la gestione delle password nel processo di creazione dell’account utente.

Chiavi

Nel contesto della crittografia, il termine “chiavi” ricorre frequentemente. Finora abbiamo parlato di hashing delle password, una forma di crittografia unidirezionale che trasforma irreversibilmente i dati, distruggendone la forma originale. Tale approccio non è adatto all’uso quotidiano: un documento cifrato e inviato via email in modo così sicuro da non poter essere mai più letto, non ha alcuna utilità. Pertanto, vogliamo crittografare i dati in modo che il mittente e il destinatario possano accedervi, mentre durante il trasferimento o l’archiviazione, le informazioni siano illeggibili.

In questo contesto entra in gioco il concetto di “chiave”. La chiave è letteralmente come quella di una serratura. Chi possiede le informazioni, le cifra con una chiave segreta. A meno che il ricevente o l’aggressore non sia in possesso della chiave, i dati sono indecifrabili, per quanto sofisticati possano essere gli algoritmi.

Rotazione delle chiavi

Sebbene le chiavi rendano possibile una crittografia affidabile, sono soggette ai rischi delle password: se la chiave viene compromessa, la sicurezza è violata. Immaginate, ad esempio, che qualcuno riesca ad accedere, anche per pochi secondi, ad un servizio come GitHub, impossessandosi di codice obsoleto. In questo codice potrebbe trovare anche le chiavi crittografiche utilizzate dall’azienda (un grave errore, archiviare le chiavi insieme al codice sorgente, ma accade con una certa frequenza). Se l’azienda non ha cambiato le chiavi (come avviene per le password), queste potranno essere utilizzate per causare gravi danni.

Per questa ragione, si è sviluppata la pratica di cambiare le chiavi frequentemente. Questo processo è definito rotazione delle chiavi e, se usate un provider PaaS cloud affidabile, dovrebbe essere disponibile come servizio automatizzato.

Credito immagine: AWS

Ad esempio, AWS offre un servizio specifico per la gestione delle chiavi, chiamato AWS Key Management Service (KMS). Un servizio automatizzato evita la necessità di cambiare e ridistribuire le chiavi tra i diversi server, rendendo questo processo semplice ed efficace, soprattutto per le grandi distribuzioni.

Crittografia a chiave pubblica

Se il discorso sulla crittografia e le chiavi vi sembra complicato, avete ragione. Proteggere le chiavi e trasmetterle in modo sicuro è un processo molto complesso, che ha posto seri ostacoli alla diffusione delle comunicazioni sicure che oggi utilizziamo quotidianamente. Ma grazie alla crittografia a chiave pubblica, possiamo comunicare e fare acquisti online in tutta sicurezza.

Questa tecnologia, risultato di un’importante avanzata matematica, ha permesso a Internet di diventare lo strumento affidabile che tutti noi conosciamo. I dettagli dell’algoritmo sono molto complessi e matematici, quindi mi limiterò a spiegarne il concetto.

Credito immagine: The Electronic Frontier Foundation

La crittografia a chiave pubblica si basa sull’uso di due chiavi: una chiave privata, che va tenuta segreta e non condivisa con nessuno, e una chiave pubblica (da cui il nome del metodo), che viene resa pubblica. Se vi devo inviare dei dati, devo prima ottenere la vostra chiave pubblica, cifrare i dati con essa, e inviarveli. A questo punto, solo voi potrete decifrarli utilizzando la vostra chiave privata e la combinazione della chiave pubblica. Finché non rivelerete la vostra chiave privata, nessuno potrà accedere ai vostri dati.

La bellezza di questo sistema sta nel fatto che io non ho bisogno di conoscere la vostra chiave privata, e chiunque intercetti il messaggio non potrà leggerlo anche se è in possesso della vostra chiave pubblica. Se vi state chiedendo come sia possibile, la risposta non tecnica sta nelle proprietà della moltiplicazione dei numeri primi:

Per i computer, è molto difficile scomporre in fattori grandi numeri primi. Quindi, se la chiave originale è molto lunga, potete essere certi che il messaggio non potrà essere decifrato nemmeno tra migliaia di anni.

Sicurezza del livello di trasporto (TLS)

Ora che avete compreso il funzionamento della crittografia a chiave pubblica, potete capire come questo meccanismo (la conoscenza della chiave pubblica del destinatario per l’invio di dati cifrati) è alla base del protocollo HTTPS, e del messaggio “Questo sito è sicuro” che Chrome visualizza nel browser. In realtà, il server e il browser stanno cifrando il traffico HTTP (le pagine web, infatti, sono lunghe stringhe di testo interpretabili dai browser) con le rispettive chiavi pubbliche, dando origine a un HTTP sicuro (HTTPS).

Credito immagine: Mozilla

È interessante notare che la crittografia non avviene sul Transport Layer. Il Modello OSI non prevede nulla sulla cifratura dei dati. I dati vengono cifrati dall’applicazione (in questo caso, il browser) prima di essere trasmessi al Transport Layer, che a sua volta li invia a destinazione, dove vengono decifrati. Tuttavia, il processo coinvolge il livello di trasporto, quindi il termine generico “sicurezza del livello di trasporto” è diventato di uso comune.

In alcuni casi, potreste imbattervi nel termine Secure Socket Layer (SSL). Si tratta dello stesso concetto di TLS, con la differenza che SSL è nato in precedenza ed è stato poi sostituito da TLS.

Crittografia dell’intero disco (Full Disk Encryption)

A volte le esigenze di sicurezza sono così stringenti da non lasciare nulla al caso. Ad esempio, i server governativi che archiviano dati biometrici non possono essere gestiti come normali server applicativi, poiché il rischio di violazione è elevatissimo. Non è sufficiente che i dati siano crittografati durante il trasferimento, ma devono essere protetti anche quando sono inattivi. Per questo motivo, si utilizza la crittografia dell’intero disco, che protegge i dati anche in caso di violazione fisica.

È importante ricordare che la crittografia dell’intero disco deve essere eseguita a livello hardware. Se cifriamo l’intero disco, anche il sistema operativo è crittografato e non può essere eseguito all’avvio del sistema. Pertanto, l’hardware deve capire che il contenuto del disco è crittografato e deve decifrare i blocchi richiesti al volo per renderli accessibili al sistema operativo. A causa di questo lavoro aggiuntivo, la crittografia completa del disco comporta operazioni di lettura e scrittura più lente, un fattore di cui i progettisti di questi sistemi devono tenere conto.

Crittografia end-to-end

A causa delle continue preoccupazioni sulla privacy e la sicurezza nei grandi social network, la “crittografia end-to-end” è un termine familiare, anche per chi non si occupa di sviluppo app.

Come abbiamo visto, la crittografia completa del disco offre una protezione completa e affidabile, ma non è adatta per l’uso quotidiano. Immaginate che Facebook voglia proteggere i dati generati e memorizzati sul vostro telefono, ma senza avere la possibilità di accedere al sistema di crittografia dell’intero telefono, compromettendo le altre funzionalità.

Per ovviare a questo problema, queste aziende hanno introdotto la crittografia end-to-end. In pratica, i dati vengono cifrati al momento della creazione, durante l’archiviazione o il trasferimento da parte dell’app. In altre parole, anche quando i dati arrivano al destinatario, sono completamente cifrati e accessibili solo dal telefono del destinatario.

Credito immagine: Google

È importante notare che la crittografia End-to-End (E2E) non garantisce una sicurezza matematica assoluta, come la crittografia a chiave pubblica. Si tratta di una crittografia standard in cui la chiave è archiviata dall’azienda, e i vostri messaggi sono sicuri nella misura in cui l’azienda decide di proteggerli.

Conclusione 👩‍🏫

Probabilmente avevate già sentito parlare di questi termini. Magari anche di tutti. In questo caso, vi incoraggio a rivedere la vostra conoscenza di questi concetti, e a valutare quanto seriamente li prendete. Ricordate che la sicurezza dei dati delle app è una lotta che va vinta costantemente, e non una sola volta. Anche una singola violazione può distruggere interi settori, carriere e persino vite!