Sei sulla pagina 1di 31

Tradotto dal Inglese al Italiano - www.onlinedoctranslator.

com

Peccato 21: usare la crittografia sbagliata 329

- Se puoi farlo senza interrompere le app esistenti, scarta il primo 1K circa del flusso di
crittografia: crittografa semplicemente un blocco da 1K e gettalo via, quindi avvia la vera
crittografia.

Successivamente, chiediti: "Perché stiamo usando RC4 e non un codice a blocchi?" La solita ragione è che
RC4 è veloce, e lo è, ma quando tutto è stato detto e fatto, quando si tiene conto del traffico di rete, dell'I/O
del disco, di altra crittografia a chiave pubblica, dei controlli di controllo degli accessi e così via, le prestazioni
aumentano di RC4 su AES è trascurabile nelle applicazioni del mondo reale. Se hai bisogno di utilizzare un
cifrario a blocchi, come AES, in una modalità simile a un cifrario a flusso, puoi farlo selezionando la modalità di
concatenamento. Ad esempio, è possibile utilizzare la modalità CTR (contatore) se disponibile o la modalità
CFB (feedback di cifratura) o OFB (feedback di output), che garantiscono tutte alcune capacità simili a cifratura
a flusso a una cifratura a blocchi. Ma per favore fai molta attenzione quando usi queste modalità di
concatenamento specializzate.
Un altro motivo per cui potresti voler utilizzare un cifrario a flusso è perché desideri un accesso
casuale ai dati. Se stai utilizzando una cifratura a blocchi e una delle modalità di feedback, può essere
difficile accedere ai dati nel mezzo del flusso di crittografia perché i dati in bloccoNinfluenza la chiave
utilizzata per il bloccoN+1. La risposta all'enigma dell'accesso casuale è crittografare i dati in blocchi
ragionevolmente grandi; nella crittografia agile introdotta in Office 2007 SP2, abbiamo usato una
dimensione del blocco di 4096. Questa è una dimensione conveniente perché rappresenta una pagina
di memoria su un sistema a 32 bit. Ogni blocco ottiene una nuova chiave generata. Otterrai comunque i
vantaggi crittografici del concatenamento della crittografia, ma puoi anche ottenere prestazioni
ragionevoli.
Un terzo motivo è che se i dati sono danneggiati, potresti provare a recuperare alcuni
dei dati dell'utente. Con RC4, perderai un byte. Con un cifrario a blocchi, perderai almeno
un blocco, forse tutti i blocchi rimanenti. Se adotti l'approccio di Office, non perderai tutti i
dati.

Concatenazione hash
La redenzione per sapere correttamente se due cose non sono cambiate è eseguirne l'hashing
individualmente, quindi puoi prendere un hash dei due hash risultanti o semplicemente
archiviare entrambi gli hash. Questo è esattamente il modo in cui funziona una firma digitale: un
elemento di riferimento all'interno del manifest memorizza un hash di un flusso di dati esterno. Il
manifest conterrà in genere un certo numero di riferimenti. Il manifest e il resto degli oggetti
firmati all'interno del file avranno riferimenti costruiti per verificare che il manifest non sia
cambiato e ciò che finisce per essere firmato è l'hash del set di riferimenti di primo livello. Un
altro percorso per la redenzione è che potresti inserire un valore fisso tra i due valori e se
qualcuno tenta di spostare qualcosa dall'uno all'altro, la posizione del separatore cambiata
cambierà il valore di output dell'hash.
La soluzione a un attacco di estensione della lunghezza è semplice: basta usare un HMAC e
utilizzare il segreto o l'hash del segreto come chiave. Invece di

Hash = H(segreto + dati_utente)


330 24 peccati capitali della sicurezza del software

Usa questo:

Hash = HMAC (segreto, dati utente)

Laddove il segreto viene utilizzato come chiave per l'HMAC, l'HMAC è progettato per affrontare esattamente
questo tipo di problema.

Utilizzo della redenzione primitiva crittografica errata


La tua redenzione è prendere l'elenco di tutti gli algoritmi crittografici in uso nel tuo codice e
assicurarti che ogni algoritmo in uso sia appropriato per l'attività da svolgere. È così semplice.
Dovresti tenere un "inventario crittografico" in corso.

Mancato utilizzo di Salt Redemption


Ogni volta che crei un verificatore di password, utilizza almeno 8 byte di salt, preferibilmente 16,
e se stai utilizzando uno degli algoritmi di hashing più grandi (SHA256 o SHA512), considera
l'utilizzo di più salt: non c'è motivo di preoccuparsi requisiti di archiviazione o di rete per qualcosa
di così piccolo. Assicurati che il sale sia generato da un potente generatore di numeri casuali.

Quando si crittografa un flusso di dati, utilizzare un sale decisamente nuovo per ogni nuovo
flusso: spesso è possibile utilizzare semplicemente il sale come vettore di inizializzazione quando
si genera la chiave di crittografia dall'output KDF. Un caso limite che devi assicurarti di aver
coperto è se modifichi parte del flusso, devi generare nuovo sale, generare una nuova chiave di
crittografia e riscrivere l'intero flusso.

Mancato utilizzo di un rimborso IV casuale


Ogni libreria crittografica decente include il supporto per l'impostazione dell'IV per un cifrario a blocchi concatenato.
Ad esempio, in C#, puoi usare codice come questo:

AesManaged aes = new AesManaged(); RNGCryptoServiceProvider rng = nuovo


RNGCryptoServiceProvider(); rng.GetBytes(aes.IV);

Utilizzo di una funzione di derivazione in chiave debole Redemption


Usa la funzione PBKDF2 documentata in RFC 2898. Se stai usando .NET, è molto semplice: c'è una
classe, Rfc2898DeriveBytes, che supporta la generazione di una chiave direttamente da una
password o passphrase:

Rfc2898DeriveBytes b = new Rfc2898DeriveBytes(pwd, salt, iter); byte [] chiave =


b.GetBytes(32);

Java offre anche funzionalità simili:


private static final String alg = "PBKDF2WithHmacSHA1"; SecretKeyFactory skf =
SecretKeyFactory.getInstance(alg, "SunJCE");
Peccato 21: usare la crittografia sbagliata 331

Se stai programmando in un'altra lingua, non è difficile implementare il tuo codice, oppure puoi
prendere il codice di esempio da www.codeplex.com/offcrypto. Guarda nel codice di esempio della
crittografia AES; dovresti essere in grado di portarlo facilmente in qualsiasi lingua ti piaccia. Oppure
puoi trovare una libreria che implementa una delle numerose solide funzioni KDF.
Quando hai un codice che ti piace, considera di aumentare il conteggio delle iterazioni fino a quando il
tempo per eseguire una derivazione è il tempo che puoi gestire senza infastidire l'utente. È improbabile che
venga notato qualcosa di meno di ¼ di secondo.
Un'ultima nota, le versioni di Windows precedenti a Windows 7 non includono una funzione
di derivazione della chiave basata su RFC 2898, ma CryptoAPI fornisce una funzione simile,
CryptDeriveKey, che deriva una chiave da un hash della password.
La funzione di derivazione della chiave basata su RFC 2898 in Windows 7 è BCryptDeriveKey
PBKDF2.
OpenSSL, a partire dalla versione 0.9.8.X, non supporta nemmeno una funzione di derivazione delle chiavi basata
su RFC 2898, ma esiste una funzione "in qualche modo documentata":

int res = PKCS5_PBKDF2_HMAC_SHA1(password, password_len,


sale, sale_len,
iter,
keylen,
chiave);

Mancata fornitura di un controllo di integrità Rimborso


Il modo corretto per eseguire un controllo di integrità consiste nel creare un HMAC dei dati. Non
importa se prendi l'HMAC del flusso crittografato o del testo in chiaro, purché la chiave utilizzata
per creare l'HMAC sia un segreto. Se disponi di più flussi di dati, prendi in considerazione la
creazione di singoli hash HMAC per ciascun flusso.
Non commettere l'errore di utilizzare il controllo di integrità come verificatore della
password. Puoi fallire un controllo di integrità in due modi: il primo sarebbe una chiave di
crittografia errata, che ti farebbe digitare l'HMAC in modo errato. Il secondo sarebbe che
qualcosa ha cambiato i dati. In generale, ti piacerebbe sapere quale dei due è il problema
che hai.
Ecco un buon approccio per creare un verificatore di password; questo è anche documentato in
MS-OFFCRYPTO:

1. Genera un set casuale di dati, non il sale che usi per nient'altro.
2. Ottenere l'hash dei dati dal passaggio 1.
3. Crittografare i dati e archiviarli.
4. Crittografare l'hash dei dati (dal passaggio 2) e archiviarlo.
5. Memorizza anche informazioni aggiuntive: l'algoritmo di crittografia salt utilizzato nel KDF,
l'algoritmo di hashing utilizzato dal KDF, il conteggio delle iterazioni, ecc.
332 24 peccati capitali della sicurezza del software

Per verificare la password, decifra i dati casuali, esegui l'hash e confrontali con l'hash
decrittografato che hai memorizzato con essa. Esistono molti modi per creare un verificatore di
password: questo è solo uno che abbiamo utilizzato. Il codice per farlo è anche su www .
codeplex.com/offcrypto.

Mancato utilizzo della redenzione della crittografia agile


Per una funzione di derivazione della chiave o un verificatore, la redenzione è semplice come
memorizzare il nome dell'algoritmo di derivazione e il conteggio delle iterazioni. Per gli algoritmi
simmetrici, dovresti consentire la configurazione delle modalità di concatenamento e riempimento.
Consigliamo di limitare il possibile numero di permutazioni ove possibile; ad esempio, avere una
dimensione del blocco di cifratura di un byte può causare alcuni difficili problemi di progettazione e
potrebbe essere più semplice semplicemente non consentire algoritmi con una dimensione del blocco
di un byte (in genere, questi saranno cifrari a flusso e quello che avresti è più probabile imbattersi in
RC4, che dovrebbe comunque essere evitato). Ipoteticamente, un algoritmo di crittografia potrebbe
avere diverse dimensioni dei blocchi di input e output, ma nessuno degli algoritmi comuni in uso oggi
lo fa e semplificherà la tua implementazione per richiedere che questi siano gli stessi.
Se stai scrivendo codice per Windows, la nuova crittografia CNG disponibile in Windows Vista e versioni
successive consente ai clienti di aggiungere in modo relativamente semplice la propria crittografia al sistema
operativo e di utilizzarla per il tuo codice. Consigliamo di prendere di mira la libreria di crittografia CNG, a
meno che il supporto di Windows XP non sia un requisito fondamentale. Puoi raggiungere alcuni degli stessi
obiettivi con CAPI, ma richiede un po' più di lavoro.
Infine, se memorizzi i dati di configurazione crittografica in un file o nel registro di Windows,
assicurati che sia protetto da autorizzazioni in modo che solo gli utenti fidati possano modificare la
politica crittografica. Vedi Sin 17 per maggiori dettagli.

Utilizzo del protocollo di comunicazione errato Riscatto


La redenzione qui è semplice: non utilizzare SSL2; utilizzare SSL3 o TLS.

MISURE EXTRA DIFENSIVE


Non ce ne sono; non c'è ripiego per un uso scadente della crittografia. Stai attento.

ALTRE RISORSE
- “MD5 considerato dannoso oggi: creazione di un certificato CA non autorizzato" di
Sotirov, A. et al.: www.win.tue.nl/hashclash/rogue-ca/
- “Deploying New Hash Functions” di Bellovin & Rescorla:
www.cs.columbia.edu/~smb/talks/talk-newhash-nist.pdf
Peccato 21: usare la crittografia sbagliata 333

- RFC 4772, "Implicazioni sulla sicurezza dell'utilizzo del Data Encryption Standard (DES)":
www.rfc-editor.org/rfc/rfc4772.txt
- “[MS-OFFCRYPTO]: specifica della struttura di crittografia dei documenti di Office”:
http://msdn.microsoft.com/en-us/library/cc313071.aspx
- “Office Crypto KDF Details” di David LeBlanc: http://blogs.msdn.com/
david_leblanc/archive/2008/12/05/office-crypto-kdf-details.aspx
- “Con la crittografia a 256 bit, le password di Acrobat 9 sono ancora facili da decifrare”
di Dancho Danchev: http://blogs.zdnet.com/security/?p=2271

- Esempi di crittografia di Microsoft Office di David LeBlanc:


www.codeplex.com/offcrypto
- Modalità ECB e Linux Penguin: http://en.wikipedia.org/wiki/
Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29

RIEPILOGO
- Fareutilizzare SSL 3 o TLS1 per la protezione del canale.

- Fareutilizzare sale casuale quando appropriato.

- Fareusa un IV casuale per cifrari a blocchi concatenati.

- Fareutilizzare algoritmi crittografici appropriati. Ad esempio, AES per la crittografia


simmetrica e la suite SHA-2 per l'hashing.
- Noncostruisci la tua criptovaluta.
- Nonhash dati concatenati.
- Noncostruisci il tuo protocollo sicuro quando un protocollo di livello superiore funziona altrettanto
bene (probabilmente meglio!).

- Nonutilizzare MD4 o MD5, se non per scopi non crittografici.


- Nonusa SHA-1 nel nuovo codice.
- Nonusa DES.
- Nonusa RC4 a meno che tu non sappia davvero cosa stai facendo.

- Nonutilizzare la modalità ECB a meno che non sia assolutamente necessario.

- Prendere in considerazioneeliminare gradualmente DES, 2-key 3DES e SHA-1 nel codice esistente.

- Prendere in considerazioneutilizzando CRC64 come algoritmo di checksum anziché MD4 o MD5.


Questa pagina è stata lasciata vuota intenzionalmente
IV
PECCATI DI RETE

335
Questa pagina è stata lasciata vuota intenzionalmente
22
Non riuscire a proteggere
Traffico di rete

337
338 24 peccati capitali della sicurezza del software

PANORAMICA DEL PECCATO


Immagina di essere a una conferenza con connettività Wi-Fi gratuita. Mentre navighi sul Web o leggi la
tua posta elettronica, tutte le immagini che cerchi di scaricare vengono sostituite con un'immagine che
non vuoi vedere. Nel frattempo, gli aggressori hanno acquisito le tue informazioni di accesso per la
posta elettronica e la messaggistica istantanea. È già successo (ad esempio, è un trucco standard in
conferenze come Defcon) e ci sono strumenti che rendono facile lanciare attacchi come questo.
Un professionista della sicurezza era solito tenere discorsi sulla sicurezza della posta elettronica e,
alla fine di un discorso, annunciava un "vincitore fortunato". Questa persona otterrebbe una maglietta
con le sue informazioni di accesso e-mail su di essa. Qualcun altro aveva usato uno sniffer, identificato
il nome utente e la password e scritto le informazioni su una maglietta con un pennarello durante il
discorso. È triste, davvero: le persone di solito sono entusiaste di aver vinto qualcosa, senza rendersi
conto di non aver partecipato intenzionalmente a nessun concorso. Poi, quando capiscono cosa sta
succedendo, la loro eccitazione si trasforma in grande imbarazzo! Durante una conferenza è tutto
divertimento, ma la triste verità è che, in molti ambienti, la posta elettronica non riceve un'adeguata
protezione in transito, a causa di protocolli mal progettati.
Questi tipi di attacchi sono possibili perché così tanti protocolli di rete non riescono a
proteggere adeguatamente il traffico di rete. Molti protocolli importanti, come SMTP (Simple Mail
Transfer Protocol) per la trasmissione della posta, IMAP (Internet Message Access Protocol) e
POP (Post Office Protocol) per la consegna della posta, SNMP (Simple Network Management
Protocol) e HTTP (Hypertext Transfer Protocol) per la navigazione web non forniscono alcuna
sicurezza o, al massimo, forniscono meccanismi di autenticazione di base facilmente attaccabili. I
protocolli principali in genere forniscono alternative più sicure, ma le persone tendono a non
utilizzare le alternative, perché i protocolli più vecchi e meno sicuri sono onnipresenti, sebbene in
alcuni casi i protocolli più sicuri vengano introdotti gradualmente. Ad esempio, telnet, rlogon e
rsh erano comuni un tempo ma sono stati in gran parte sostituiti da ssh, che è un design sicuro.
Sfortunatamente, ci sono molti protocolli che non hanno opzioni più sicure!

RIFERIMENTI CWE
CWE offre la seguente debolezza che riassume una variante di questo peccato:

- CWE-319: trasmissione in chiaro di informazioni sensibili


Ma la “protezione dei dati” non si limita al mantenimento della segretezza; devi anche preoccuparti della
resistenza alla manomissione e altro ancora.

LINGUE INTERESSATE
Tutte le lingue sono soggette a questo problema perché la mancata protezione del traffico di rete è un problema di
progettazione.
Peccato 22: mancata protezione del traffico di rete
339

IL PECCATO SPIEGATO
Troppi programmatori pensano che una volta che i dati vengono scaricati sulla rete, sarà molto
difficile per un utente malintenzionato fare qualcosa di nefasto, oltre a leggerli. Spesso lo
sviluppatore non si preoccupa della riservatezza a livello di rete perché non è stato un requisito
esplicito da parte dei clienti. Ma esistono strumenti là fuori che possono reindirizzare il traffico e
persino dare all'attaccante la possibilità di manipolare il flusso di dati.
Il modello mentale che la maggior parte delle persone ha è che i dati vengono inviati a monte troppo
rapidamente perché un utente malintenzionato possa entrare nel mezzo, quindi passano da un router all'altro, dove
sono al sicuro. Quei programmatori che hanno interruttori sulle loro reti spesso si sentono più sicuri che non ci
saranno problemi.
Nel mondo reale, se gli aggressori hanno un punto d'appoggio sulla LAN locale per entrambi i lati
di una comunicazione, possono avere buone possibilità di lanciare un attacco basato sulla rete,
sfruttando la mancanza di sicurezza nel protocollo di rete. Se gli aggressori si trovano sullo stesso
segmento di rete condiviso di uno degli endpoint (ad esempio, collegati a un hub), vedono tutto il
traffico su quel segmento e di solito possono organizzarsi per intercettarlo tutto. Anche se gli
aggressori sono collegati a uno switch (un hub in cui le singole porte non vedono il traffico reciproco),
esiste una tecnica chiamata spoofing ARP (Address Resolution Protocol), in cui gli aggressori fingono di
essere il gateway e reindirizzano tutto il traffico a se stessi . Possono quindi inviare il traffico dopo
averlo elaborato.
Esistono molte altre tecniche che raggiungono lo stesso obiettivo; ad esempio, molti switch
possono essere inondati da ARPmodalità promiscuadove fondamentalmente finiscono per
comportarsi come hub. Se riesci a vedere le richieste DHCP, hai abbastanza informazioni per
formare una risposta che dica alla vittima che il tuo sistema è ora il gateway, e anche se la
risposta effettiva arriva prima, puoi costringere la vittima a rinegoziare. Se la rete supporta IPv6,
il Neighbor Discovery Protocol può essere utilizzato per trovare gli altri host e puoi quindi
convincerli che sei il router!
Come funziona un attacco ARP? ARP è un protocollo per la mappatura degli indirizzi di livello 2
(codice di autenticazione del messaggio Ethernet o MAC) agli indirizzi di livello 3 (protocollo Internet o
IP) (il livello 1 è il trasporto fisico effettivo, in genere impulsi su un filo). Gli aggressori pubblicizzano
semplicemente l'indirizzo della scheda di rete (noto come indirizzo MAC [Media Access Control]) come
indirizzo appartenente all'IP del gateway. Una volta che le macchine vedono il cambiamento,
inizieranno a instradare tutto il loro traffico attraverso un utente malintenzionato. Lo spoofing ARP non
ha una soluzione pratica e universale a breve termine, perché devono esserci servizi fondamentali a
livello Ethernet che solo ora iniziano a essere discussi all'interno degli organismi di standardizzazione.
Tutti questi problemi peggiorano sulla maggior parte delle reti wireless, a meno che la rete non sia
stata protetta utilizzando i più recenti protocolli di sicurezza wireless, che richiedono che entrambi i
sistemi si autentichino l'uno con l'altro. Sebbene ciò sia comune nelle reti wireless aziendali di grandi
dimensioni, lo stesso approccio può essere utilizzato sulle reti cablate per fornire lo stesso livello di
protezione, ma è molto raro vedere questo livello di sicurezza nella pratica.
340 24 peccati capitali della sicurezza del software

Anche a livello di router, probabilmente non è sicuro presumere che non ci siano vettori di attacco.
I router più diffusi sono programmi C/C++ grandi e complessi e possono essere soggetti a buffer
overflow e altri peccati che affliggono le applicazioni C/C++ che consentirebbero a un utente
malintenzionato di eseguire codice arbitrario su un router. A peggiorare le cose, molti router vengono
forniti con password predefinite (vedi Sin 19) e anche se sono disponibili controlli di accesso sofisticati
per le interfacce di gestione, gli amministratori spesso non impostano la sicurezza o non lo fanno in
modo coerente. Come con qualsiasi software, i fornitori di router dovrebbero cercare di migliorare i
propri processi utilizzando tecniche all'avanguardia per il ciclo di vita dello sviluppo del software che
migliorano la sicurezza. Ci sono stati overflow del buffer nei router prima. Vedi, ad esempio, dal
dizionario Common Vulnerabilities and Exposures (CVE) (su http://cve.mitre.org): CVE-2002-0813,
CVE-2003-0100 e CVE-2003-0647. In effetti, ci sono molti aggressori specializzati nella compromissione
dei router: anche se non c'è vulnerabilità diretta, ci sono sempre attacchi per indovinare la password e
mentre un router può essere configurato per consentire solo l'amministrazione da un insieme ristretto
di indirizzi, raramente sistemati in quel modo.
In effetti, una volta c'era un gruppo numeroso e ben noto di ricercatori di sicurezza molto acuti a
cui è stata compromessa la rete perché qualcuno si è preso la briga di assumere il controllo del loro
provider di servizi Internet e di fiutare il loro traffico fino a quando non sono riusciti a entrare. Le reti
fanno tutto tipo di cose maleducate, e questo prima che le persone cattive decidano di rendere la vita
difficile. La scommessa più sicura è presumere che gli aggressori possano intromettersi in tutto il
traffico di rete e modificarlo.
Gli attacchi di rete possono assumere un'ampia varietà di forme, come descritto di seguito.

- IntercettazioneUn utente malintenzionato ascolta la conversazione e registra tutte le


informazioni preziose, come nomi di accesso e password. Anche se la password non è in
una forma leggibile dall'uomo (e spesso lo è), è quasi sempre possibile prendere dati
intercettati ed eseguire un attacco del dizionario a forza bruta per recuperare la password.
A volte, la password può essere recuperata direttamente, poiché è solo offuscata.

- RigiocareL'attaccante prende i dati esistenti da un flusso di dati e li riproduce. Questo può


essere un intero flusso di dati o solo una parte di uno. Ad esempio, si potrebbero riprodurre
le informazioni di autenticazione per accedere come qualcun altro e quindi iniziare una
nuova conversazione.

- SpoofingL'attaccante imita i dati come se provenissero da una delle due parti, ma i


dati sono controllati dall'attaccante. Lo spoofing generalmente comporta l'avvio di
una nuova connessione, utilizzando potenzialmente informazioni di autenticazione
ripetute. In alcuni casi, gli attacchi di spoofing possono essere lanciati contro
connessioni di rete già stabilite, in particolare connessioni virtuali in esecuzione su un
trasporto "senza connessione" (in genere, User Datagram Protocol o UDP).

Un attacco di spoofing può essere difficile da realizzare, a seconda del trasporto e del
protocollo. Ad esempio, se è possibile prevedere un numero di sequenza iniziale TCP
Peccato 22: mancata protezione del traffico di rete
341

(come era un problema comune) e il protocollo non richiede la visualizzazione delle


risposte, è possibile lanciare un attacco di spoofing cieco. Un esempio di protocollo
che potrebbe essere attaccato con un attacco di blind spoofing è SMTP; il client non ha
bisogno di vedere le risposte dal server. Un controesempio sarebbe un protocollo di
autenticazione challenge-response, come NTLM o Kerberos.

Quando il protocollo sottostante è senza connessione, lo spoofing diventa molto semplice se


il protocollo non è sicuro. Un esempio di attacco di spoofing senza connessione (ora risolto)
consiste nell'inviare un pacchetto non richiesto alla porta di localizzazione RPC UDP (135) di
un sistema Windows NT 4.0 che finge di essere un altro sistema. La vittima 1 risponde alla
vittima 2 con una risposta di errore e la vittima 2 risponde con un'altra risposta di errore. La
"lotta per il cibo della rete" continua fino a quando la larghezza di banda della rete e/o le
risorse della CPU su entrambi i sistemi non vengono consumate. Se la risoluzione dei nomi
può essere danneggiata, il che sfortunatamente non è difficile, allora non importa quanto sia
difficile falsificare una connessione TCP: la tua vittima viene direttamente da te e puoi
inoltrare ciò che ti piace al server dall'altra parte o fingi semplicemente di essere l'altro
server.

- ManomissioneL'attaccante modifica i dati sul filo, forse facendo qualcosa di innocuo come
cambiare un bit 1 in un bit 0. Nei protocolli basati su TCP, anche l'attaccante deve correggere
il checksum, ma il checksum è stato progettato per essere estremamente veloce perché i
router hanno legittimamente bisogno di ricalcolare e modificare i checksum al volo.

- DirottamentoL'aggressore attende una connessione stabilita e quindi interrompe una


delle parti, falsificando i dati della parte per il resto della conversazione. I protocolli
moderni rendono difficile l'iniezione/spoofing di nuovo traffico nel mezzo di una
conversazione (almeno quando i sistemi operativi degli endpoint sono aggiornati), ma
l'hijacking non è ancora impossibile.

Se sei preoccupato per la sicurezza delle tue connessioni di rete, dovresti sapere quali
tipi di servizi devono fornire le tue applicazioni. Parleremo di questi servizi di base qui,
quindi parleremo di come raggiungere questi obiettivi nella sezione "Fasi di riscatto" più
avanti in questo capitolo. Per proteggerti dagli attacchi che abbiamo appena elencato, in
genere vorrai fornire questi servizi di sicurezza di base:

- Autenticazione inizialeLa tua applicazione deve garantire che i due endpoint siano
d'accordo su con chi stanno parlando. L'autenticazione può coinvolgere il client che
autentica il server, il server che autentica il client o entrambi. Sono disponibili
diverse tecniche di autenticazione, a seconda del design dell'applicazione. Un
esempio di un'implementazione comune utilizzata per le applicazioni Web potrebbe
essere l'autenticazione del server presso il client con SSL/TLS e quindi
l'autenticazione del client presso il server con una password.
342 24 peccati capitali della sicurezza del software

- Autenticazione continuaDopo esserti autenticato inizialmente, devi comunque assicurarti


che il resto del traffico non sia stato deviato o manomesso. Ad esempio, sebbene sia possibile
utilizzare telnet per autenticarsi in modo relativamente sicuro, la successiva conversazione di
rete non è protetta in alcun modo. Il problema di mantenere in modo errato lo stato della
sessione è molto comune tra le applicazioni web.
Un esempio di esecuzione molto scarsa dell'autenticazione continua consiste nel presentare una pagina
di accesso e quindi consentire agli aggressori di accedere direttamente alle pagine protette una volta che
conoscono l'URL corretto.

- RiservatezzaAlcuni dati richiedono assolutamente la privacy, come le transazioni con


la tua banca. Molti altri flussi di informazioni sono pubblici e non devono essere
protetti dalla fuga di informazioni. Un buon esempio potrebbe essere un servizio
orario: sappiamo tutti che ore sono, ma vorremmo assicurarci che nessuno abbia
manomesso le informazioni e che stiamo parlando con il server orario giusto.

Ci sono casi in cui vuoi comunque assicurarti che tutti i dati siano autentici e che vada bene
senza crittografia. Di solito non ha senso mantenere la riservatezza senza un controllo di
integrità sia iniziale che continuo. Ad esempio, quando un utente malintenzionato utilizza
una modalità di cifratura a flusso come RC4 (questo include anche le modalità operative
popolari per le cifrature a blocchi), l'attaccante può capovolgere bit casuali nel testo cifrato e,
senza un adeguato controllo dell'integrità del messaggio, in genere non si potrebbe mai
Sapere. Se gli aggressori conoscono il formato dei dati, possono fare cose ancora più crudeli
capovolgendo bit specifici.

Sebbene RC4 abbia alcune buone proprietà in termini di crittografia del traffico di rete,
non è più qualcosa che raccomanderemmo a causa del problema con il bit flipping,
chiavi che sono relativamente deboli per gli standard moderni, nonché alcuni problemi
crittografici più arcani. Inoltre, è noto che le reti capovolgono i bit in modo alquanto
casuale anche senza che gli aggressori creino problemi. Il controllo dell'integrità
dovrebbe far parte di qualsiasi solida conversazione di rete.

Peccati correlati
Sebbene sia fin troppo comune omettere semplicemente la sicurezza in un'applicazione, è spesso
il caso che i protocolli basati su PKI, come Secure Sockets Layer/Transport Layer Security (SSL/
TLS), siano utilizzati in modo errato (Sin 23) e non siano corretti spesso vengono utilizzati anche
algoritmi crittografici (Sin 21). Uno degli errori più comuni è confondere SSL utilizzando un
certificato autofirmato con la crittografia: SSL su un certificato autofirmato è soggetto ad attacchi
MITM e equivale effettivamente a offuscamento. L'autenticazione è anche una parte importante
della connettività di rete sicura ed è anche un punto di errore comune (ad esempio, Sins 22 e 18).
Inoltre, per molti protocolli di rete sicuri sono richiesti numeri casuali crittograficamente forti (Sin
20).
Peccato 22: mancata protezione del traffico di rete
343

INDIVIDUARE IL MODELLO DEL PECCATO


Questo peccato di solito si verifica quando

- Un'applicazione utilizza una rete. (Dimmi uno che non lo fa!)


- I progettisti trascurano o sottovalutano i rischi a livello di rete.

Ad esempio, un argomento comune è "prevediamo che questa porta sarà disponibile solo
dietro un firewall". In pratica, la maggior parte degli incidenti di sicurezza della rete ha qualche
elemento interno, che si tratti di un dipendente scontento o corrotto, amico di un dipendente,
custode, cliente o fornitore che visita il luogo di lavoro o così via. Inoltre, non è raro assumere un
firewall, solo per avere una politica locale diversa. E quante persone conosci che hanno avuto
problemi di connettività di rete, quindi disabilitano i loro firewall e una volta risolto il problema si
dimenticano di riattivarli? In una rete di grandi dimensioni con molti punti di ingresso, il concetto
di rete interna protetta è obsoleto. Le grandi reti interne dovrebbero essere pensate come
ambienti semi-pubblici e semi-ostili.

INDIVIDUARE IL PECCATO DURANTE LA REVISIONE DEL CODICE


Se non hai identificato la superficie di attacco di un'applicazione (tutti i punti di ingresso di input), allora
è una delle prime cose che dovresti fare. I tuoi modelli di minaccia, se disponibili, dovrebbero già
riflettere i punti di ingresso. Nella maggior parte dei casi, le connessioni di rete dovrebbero
probabilmente utilizzare solo SSL/TLS, nel qual caso puoi seguire Sin 23 per indicazioni per ogni punto
di ingresso basato sulla rete che identifichi.
In caso contrario, per ogni punto di ingresso che potrebbe provenire dalla rete, determinare
quale meccanismo viene utilizzato per la riservatezza dei dati in blocco, l'autenticazione iniziale e
l'autenticazione continua. A volte non ce ne saranno, ma sarà considerato un rischio accettabile,
in particolare quando la posta elettronica fa parte del sistema.
Se c'è riservatezza per una particolare connessione di rete, dovresti provare a determinare se sta facendo
il lavoro. Questo può essere complicato, perché spesso richiede una comprensione ragionevolmente
approfondita della crittografia sottostante. Un'area particolarmente importante per la revisione del codice è la
verifica dell'uso corretto dei sistemi basati su PKI come SSL (vedere Sin 23 per i dettagli).

TECNICHE DI PROVA PER TROVARE IL PECCATO


Determinare se i dati sono crittografati o meno è in genere un'attività semplice, che puoi eseguire
semplicemente osservando l'acquisizione di un pacchetto. Tuttavia, dimostrare che l'autenticazione dei
messaggi è in uso può essere davvero difficile quando si eseguono test rigorosi. Puoi avere un'idea se il
messaggio non è crittografato, ma alla fine di ogni messaggio sembra esserci un numero fisso di byte di dati
dall'aspetto casuale. È possibile verificare se un'applicazione è in grado di rilevare la manomissione dei
messaggi apportando piccole modifiche che non interrompano completamente il file
344 24 peccati capitali della sicurezza del software

formato complessivo. Un problema difficile nel testare le applicazioni può essere vedere come
apportare modifiche che non testano alcuni protocolli o trasporti sottostanti. Ad esempio, il semplice
capovolgimento casuale di bit in un pacchetto di rete testerà lo stack TCP, non l'applicazione.
È anche abbastanza semplice determinare dal punto di vista del test se stai visualizzando dati
crittografati con SSL. È possibile utilizzare ssldump (www.rtfm.com/ssldump/) per rilevare il
traffico crittografato con SSL.
In definitiva, testare per vedere se le persone stanno usando gli algoritmi giusti e li usano nel
modo giusto è un compito incredibilmente difficile da fare, specialmente se stai solo facendo test black-
box. Pertanto, per controlli più sofisticati (assicurandosi che le persone utilizzino buone modalità,
materiale chiave forte e simili), è molto più efficace eseguire semplicemente la progettazione e la
revisione del codice.

ESEMPIO PECCATI
Internet ha trascorso la sua infanzia come progetto di ricerca. C'era una fiducia diffusa e
non si pensava molto alla sicurezza. Certo, c'erano password sugli account di accesso, ma
non è stato fatto molto oltre a questo. Di conseguenza, la maggior parte dei protocolli più
vecchi e importanti non ha una sicurezza significativa.

TCP/IP
Il protocollo Internet (IP) e i protocolli basati su di esso, ovvero TCP (Transmission Control Protocol),
ICMP e UDP, non forniscono alcuna garanzia per i servizi di sicurezza di base come la riservatezza e
l'autenticazione continua dei messaggi. TCP utilizza checksum che hanno lo scopo di proteggere dalla
corruzione casuale della rete, ma non è crittograficamente forte e può essere facilmente ripristinato e
spesso viene ripristinato quando i dispositivi devono riscrivere parti di un'intestazione di pacchetto per
un tunnel o un proxy. Infatti, essere in grado di ricalcolare un checksum in modo che i pacchetti
possano essere modificati al volo dai dispositivi di rete senza una significativa perdita di prestazioni è
assolutamente in base alla progettazione.
IPv6 affronta questi problemi aggiungendo servizi di sicurezza opzionali. Questi servizi
di sicurezza (noti come IPSec) sono stati considerati così utili che sono stati ampiamente
implementati sulle tradizionali reti IPv4. Ma oggi sono generalmente utilizzati per reti
private virtuali aziendali (VPN) e simili e non sono ancora utilizzati universalmente, come
originariamente previsto.

Protocolli di posta elettronica

La posta elettronica è un altro esempio in cui i protocolli non hanno tradizionalmente protetto i dati in
transito. Sebbene ora esistano versioni ottimizzate per SSL di SMTP, Post Office Protocol 3 (POP3) e IMAP, non
sono sempre utilizzate e potrebbero non essere sempre supportate da alcuni popolari lettori di posta
elettronica, sebbene alcuni supportino almeno la crittografia e l'autenticazione per il trasferimento interno
della posta. Spesso puoi mettere uno sniffer su una rete locale e leggere la posta elettronica del tuo collega.
Alcuni dei più popolari server di posta elettronica di livello aziendale lo fanno
Peccato 22: mancata protezione del traffico di rete
345

comunicare in modo sicuro con i client, almeno fintanto che i messaggi rimangono all'interno
della rete aziendale e molti lettori di posta moderni supportano l'esecuzione di POP, IMAP e
SMTP su SSL.

E*COMMERCIO
L'algoritmo di crittografia originale di E*TRADE prevedeva l'XORing dei dati con un valore fisso. Questo
è un approccio facile da implementare, ma è anche facile da rompere. Un buon crittoanalista dilettante
può capire che questo è ciò che sta accadendo solo raccogliendo ed esaminando abbastanza dati che
escono in rete. Non ci vogliono molti dati o tempo per capire cosa sia la cosiddetta "chiave di
crittografia" e rompere completamente lo schema. A peggiorare le cose, XOR non spera nemmeno di
fornire un'autenticazione continua dei messaggi, quindi è stato facile per gli aggressori esperti lanciare
tutti gli attacchi di cui abbiamo parlato in questo capitolo.

FASI DI RISCATTO
In generale, si consiglia di utilizzare SSL/TLS per qualsiasi connessione di rete, se possibile,
oppure un altro protocollo ben noto, come Kerberos. Assicurati di utilizzare SSL (e qualsiasi
protocollo basato su PKI) in conformità con la nostra guida in Sin 23.
Se la tua applicazione non consente SSL/TLS, un approccio consiste nel creare un proxy locale per
implementare la sicurezza, come Stunnel. Un'altra alternativa consiste nell'utilizzare IPSec o qualche altra
tecnologia VPN per ridurre l'esposizione ai problemi di rete. Uno dei motivi addotti da alcune persone per
evitare SSL/TLS è l'overhead di autenticazione. SSL utilizza la crittografia a chiave pubblica che può essere
costosa e può potenzialmente lasciarti esposto ad attacchi di negazione del servizio. Se questa è una grande
preoccupazione, ci sono sicuramente soluzioni a livello di rete, come il bilanciamento del carico, che puoi
usare.
Ecco alcune indicazioni di base:

- Evita di farlo da solo. Utilizzare SSL, ssh o le API (Application Programming


Interface) basate su Kerberos fornite da Windows nelle librerie DCOM/RPC
(Distributed Component Object Model/Remote Procedure Calls).
- Se decidi che devi farlo tu stesso, prima vai a rivedere tutti i modi in cui NIS,
Kerberos e NTLM hanno fallito negli ultimi 20 anni. Se non hai ancora scelto
una soluzione standard, utilizza tecniche crittografiche ben note. Vedi Peccati
19–21 per i nostri migliori consigli sulla crittografia.
- Se la tua applicazione prevede il trasferimento di dati in blocco e la privacy non è richiesta, prendi in
considerazione la semplice trasmissione di un hash o HMAC dei dati attraverso un canale sicuro,
quindi verifica che non vi siano danneggiamenti o manomissioni sul lato ricevente.

Molti noti protocolli di autenticazione hanno proprietà diverse, a seconda del trasporto.
Ad esempio, Kerberos può normalmente autenticare il server, ma l'autenticazione del
server non è disponibile quando si accede tramite HTTP e, come accennato in precedenza,
NTLM su HTTP è soggetto ad attacchi di riproduzione quando non è vulnerabile
346 24 peccati capitali della sicurezza del software

per ripetere gli attacchi quando viene utilizzato su trasporti ordinari, come TCP/IP. Assicurati di
comprendere le sfumature di come si comporta la tua scelta di autenticazione per il trasporto
con cui stai lavorando.

MISURE EXTRA DIFENSIVE


Pratica una migliore gestione delle chiavi. Un buon modo è utilizzare l'API di protezione dei dati su
Windows o le API CDSA.

ALTRE RISORSE
- Lo strumento ssldump per esaminare il traffico di rete SSL: www.rtfm.com/ssldump
- Il proxy SSL di Stunnel: www.stunnel.org/

RIEPILOGO
- Fareutilizzare protocolli di sicurezza collaudati come SSL/TLS e IPSec.
- Fareutilizzare un forte meccanismo di autenticazione iniziale.

- Fareeseguire l'autenticazione continua dei messaggi per tutto il traffico di rete


prodotto dall'applicazione.

- Farecrittografare tutti i dati per i quali la privacy è una preoccupazione. Err sul lato della privacy.

- Fareusa SSL/TLS per tutte le tue esigenze crittografiche on-the-wire, se possibile.


Funziona!
- Nonignora la sicurezza dei tuoi dati in transito.
- Nonesitare a crittografare i dati per motivi di efficienza. La crittografia continua è
economica.

- Nonchiavi hardcode e non pensare che XORing con una stringa fissa sia un
meccanismo di crittografia.
- Prendere in considerazioneutilizzando tecnologie a livello di rete per ridurre ulteriormente
l'esposizione ogni volta che ha senso, come firewall, VPN e bilanciatori di carico.
23
Uso improprio di PKI,
Soprattutto SSL

347
348 24 peccati capitali della sicurezza del software

PANORAMICA DEL PECCATO


L'infrastruttura a chiave pubblica, o PKI, è comune su Internet. Viene utilizzato nelle comunicazioni SSL/
TLS (di seguito SSL); viene utilizzato in IPSec, accesso con smart card e posta elettronica protetta
tramite S/MIME. Ma è notoriamente difficile avere ragione.
Da questo punto in poi, parleremo in termini di SSL perché è prevalente, ma per la maggior parte degli
scopi, stiamo davvero parlando di peccati correlati a PKI nel loro insieme.
SSL, Secure Sockets Layer (insieme al suo successore, Transport Layer Security o TLS), è il
mezzo più popolare per creare connessioni di rete sicure. È ampiamente utilizzato nei browser
Web per proteggere operazioni potenzialmente sensibili come il banking basato su HTTP perché,
dal punto di vista dell'utente, "funziona".
Il grosso problema con SSL, tuttavia, è che utilizza PKI e le PKI sono davvero difficili da ottenere
correttamente. Il problema è duplice: una PKI soffre di problemi di gestione e la gestione dei certificati
è notoriamente difficile da programmare. Diciamo che sono difficili perché ci sono un buon numero di
parti mobili in PKI e tutte devono essere allineate. Inoltre, non esiste un buon modo per presentare
un'interfaccia utente utilizzabile agli utenti del browser con SSL.
Molti sviluppatori pensano che "sicurezza" e "SSL" siano sinonimi perché SSL è così
comunemente usato e l'utilità di SSL va oltre la protezione del solo traffico HTTP.
I peccati iniziano a insinuarsi nelle applicazioni basate su SSL quando scelgono erroneamente i
servizi di sicurezza offerti da SSL. Molti algoritmi di sicurezza, incluso SSL, forniscono tre servizi di
sicurezza distinti e facoltativi:

- Autenticazione (server e/o client)


- Crittografia del canale

- Controllo dell'integrità del canale

Il primo punto dell'elenco è l'obiettivo principale di questo capitolo, mentre gli altri due punti
sono l'argomento di Sin 21, sotto il titolo "Utilizzo della primitiva crittografica errata".
Quando crei un'applicazione che utilizza SSL, devi considerare quale di queste proprietà di
sicurezza richiede la tua applicazione. Probabilmente li vuoi tutti e tre. È anche importante capire
che tutte queste proprietà di sicurezza sono facoltative!
SSL sembra semplice. Per la maggior parte dei programmatori, sembra un drop-in trasparente per
i socket TCP, dove puoi semplicemente sostituire i normali socket TCP con i socket SSL, aggiungere un
semplice login che viene eseguito sulla connessione SSL e farla finita. Naturalmente, tutto questo è
molto semplice quando si utilizza HTTPS (HTTP, o Hypertext Transfer Protocol, su SSL), poiché il
browser si occupa di tutto il lavoro sporco. Ma se stai aggiungendo il supporto SSL alla tua
applicazione, devi essere consapevole dei peccati.

RIFERIMENTI CWE
Il punto debole principale per questo peccato è CWE-295: Problemi con i certificati, e sotto questo ci sono i
problemi che delineiamo nel resto di questo capitolo, inclusi
Peccato 23: uso improprio di PKI, in particolare SSL
349

- CWE-296: mancato rispetto della catena di fiducia nella convalida del certificato

- CWE-297: mancata convalida dei dati del certificato specifico dell'host

- CWE-298: mancata convalida della scadenza del certificato

- CWE-299: mancata verifica della revoca del certificato


- CWE-324: utilizzo di una chiave oltre la data di scadenza

Una mancanza di autenticazione può quindi portare a

- CWE-322: scambio di chiavi senza autenticazione dell'entità

LINGUE INTERESSATE
I problemi SSL sono in genere problemi di progettazione e non un problema con alcun linguaggio di
programmazione sottostante. Pertanto, qualsiasi lingua può essere influenzata. Le API HTTPS tendono
ad essere meno problematiche dell'SSL generico, perché il protocollo HTTPS impone controlli di
autenticazione che il protocollo SSL generico lascia come facoltativo. Di conseguenza, le API SSL di
basso livello tendono a lasciare questa responsabilità all'utente.

IL PECCATO SPIEGATO
Oggi SSL è un protocollo basato sulla connessione. L'obiettivo principale di SSL è trasferire i
messaggi tra due parti su una rete "in modo sicuro". "Sicuro" è una parola interessante, perché
significa cose diverse per persone diverse perché dipende da quale delle tre proprietà di
sicurezza (autenticazione, crittografia del canale o controllo dell'integrità del canale) scelgono.
Indipendentemente dal fatto che un'applicazione scelga di utilizzare queste proprietà di sicurezza
è il punto cruciale di questo peccato.
Per arrivare al punto in cui due parti possono avere comunicazioni sicure arbitrarie con SSL,
le due parti devono prima autenticarsi a vicenda. Per lo meno, un'applicazione o l'utente di
un'applicazione deve sapere che sta realmente intrattenendo una conversazione privata con il
server corretto. Tuttavia, il server potrebbe essere disposto a parlare con utenti anonimi. In caso
contrario, il server vorrà autenticare il client. L'autenticazione client è un'opzione all'interno del
protocollo SSL.
Se non riesci a capirlo, immagina di acquistare un oggetto online; devi sapere che stai
davvero dando la tua carta di credito al sito web che pensi, ma il sito web accetterà carte di
credito da chiunque!
I passaggi di autenticazione all'interno di SSL utilizzano una PKI (vale a dire, utilizza i
certificati), ed è qui che le cose possono diventare peccaminose se non si eseguono i controlli PKI
appropriati. Non è intenzione di questo capitolo spiegare le viscere di PKI, o essere pedanti, i
certificati X.509 usati da SSL; il lettore è invitato a fare riferimento ad alcuni degli eccellenti
riferimenti nella sezione "Altre risorse" di questo capitolo. In particolare, dovresti leggere RFC
2459, "Internet X.509 Public Key Infrastructure: Certificate and CRL Profile". È asciutto ma
completo.
350 24 peccati capitali della sicurezza del software

Quindi, senza entrare in tutti i dettagli cruenti della PKI X.509, è importante che l'applicazione client
esegua i seguenti passaggi di convalida quando esegue l'autenticazione del server; il mancato rispetto di uno
di questi passaggi è peccaminoso la maggior parte delle volte:

- Verificare che il certificato del server sia firmato da una terza parte attendibile, nota come
autorità di certificazione (CA).

- Verificare che il certificato del server sia attualmente valido. Un certificato X.509 è valido
solo per un periodo di tempo; c'è un'ora di inizio e una data di scadenza nel certificato,
proprio come con una carta di credito.

- Il nome nel certificato corrisponde all'endpoint con cui vuoi comunicare.


- Il certificato viene utilizzato per lo scopo corretto; ad esempio, viene utilizzato per l'autenticazione del
server e non per la firma della posta elettronica (S/MIME).

- Il certificato non viene revocato. Il numero di serie di un certificato viene revocato


dall'emittente se la chiave privata viene persa o compromessa o se l'emittente ritiene di
doverlo annullare per una miriade di altri motivi!

È facile per gli sviluppatori perdere uno o più di questi passaggi, ma di gran lunga il passaggio più
comunemente ignorato è non eseguire un controllo di revoca.
Se il certificato non è valido perché una o più condizioni di cui sopra non sono soddisfatte, l'applicazione
dovrebbe considerare di rifiutare il certificato e fallire la fase di autenticazione. Il problema è che l'esecuzione
di ciascuno di questi passaggi può richiedere molto codice per funzionare correttamente e quindi molti
sviluppatori ignorano uno o più passaggi.

Peccati correlati
Sebbene questo capitolo si concentri sull'uso programmatico peccaminoso del protocollo SSL, ci sono alcuni
peccati correlati; in particolare la scarsa scelta della suite di cifratura SSL, che è trattata in Sin 21, e la pessima
generazione di chiavi, trattata in Sin 20.

INDIVIDUARE IL MODELLO DEL PECCATO


Ci sono un paio di schemi di base a cui prestare attenzione; il primo copre l'errore più grave di
non eseguire correttamente la convalida del certificato:

- Viene utilizzata qualsiasi PKI, come SSL o TLS, e

- HTTPS non viene utilizzato e

- Il codice della libreria o dell'applicazione non riesce a controllare il certificato utilizzato dal
processo all'altra estremità del canale di comunicazione.
Peccato 23: uso improprio di PKI, in particolare SSL
351

INDIVIDUARE IL PECCATO DURANTE LA REVISIONE DEL CODICE


Innanzitutto, identifica tutti i punti di input della tua applicazione che provengono dalla rete. Per
ciascuno di questi punti, determinare se il codice utilizza o meno SSL. Mentre le API variano
notevolmente da libreria a libreria e da lingua a lingua, è più semplice eseguire una ricerca senza
distinzione tra maiuscole e minuscole per "SSL", "TLS" e "secure.?socket" (notare l'espressione
regolare).
Per ogni punto di ingresso di rete che utilizza SSL, verificare che il codice esegua i seguenti passaggi:

- Il certificato è firmato da una CA nota, oppure c'è una catena di firme che
riconduce a quella CA.
- Il certificato e tutti i certificati della catena rientrano nel periodo di
validità.
- Il nome host viene confrontato con il sottocampo appropriato in almeno uno dei
campi DN o nell'estensione subjectAltName X.509 v3.
- L'utilizzo del certificato è corretto; probabilmente l'autenticazione del server o
l'autenticazione del client.

- Il certificato non viene revocato. Dovrai decidere come gestire la possibilità di


un server di revoca non disponibile. A seconda delle esigenze della tua
applicazione, potresti voler ignorare questo errore o considerarlo fatale.
Possiamo immaginare scenari in cui entrambe le scelte sono appropriate.

- Il programma considera il fallimento di uno qualsiasi di questi controlli come un


errore di autenticazione e si rifiuta di stabilire una connessione.

- L'algoritmo utilizzato dal certificato non è danneggiato: non dovresti accettare


certificati firmati con hash MD5.

In molti linguaggi di programmazione, questo richiederà spesso di esaminare a fondo la


documentazione o persino l'implementazione. Ad esempio, potresti imbatterti nel seguente
codice Python utilizzando il modulo "socket" standard fornito in Python 2.4:

presa di importazione
s = socket.socket()
s.connect(('www.example.org', 123)) ssl =
socket.ssl(s)

Non è chiaro in superficie ciò che la libreria SSL controlla per impostazione predefinita. Nel caso di
Python, la risposta è che, secondo la documentazione, le librerie SSL non controllano assolutamente
nulla.
352 24 peccati capitali della sicurezza del software

Quando controlli per assicurarti che la revoca sia stata eseguita correttamente, dovresti verificare se
vengono utilizzati gli elenchi di revoca dei certificati (CRL) o l'OCSP (Online Certificate Status Protocol). Ancora
una volta, le API variano ampiamente, quindi è meglio ricercare l'API SSL effettivamente utilizzata da un
programma; ma la ricerca di "CRL" e "OCSP" senza distinzione tra maiuscole e minuscole funzionerà in un
pizzico.
Quando vengono utilizzati uno o entrambi questi meccanismi, le cose più importanti a cui prestare attenzione
sono le seguenti:

- Questo viene fatto prima che i dati vengano inviati?

- Cosa succede quando il controllo fallisce?

- Nel caso dei CRL, con quale frequenza vengono scaricati?


- Nel caso dei CRL, i CRL stessi sono convalidati proprio come i certificati
(soprattutto se vengono scaricati tramite semplice HTTP o LDAP)?

Fai attenzione al codice che guarda semplicemente "all'interno" del certificato per alcuni
dettagli come il DN e non esegue le operazioni di convalida della firma crittografica appropriate.
Il seguente codice è peccaminoso perché controlla solo per vedere se il certificato ha il testo "
www.esempio.com",e chiunque potrebbe rilasciare a se stesso un certificato con questo nome.

nome stringa = cert.GetNameInfo(X509NameType.SimpleName,false); if (nome ==


"www.esempio.com") {
// Fantastico, *potremmo* parlare con www.example.com!
}

TECNICHE DI PROVA PER TROVARE IL PECCATO


Esistono diversi strumenti che automatizzeranno un attacco MITM contro HTTP su SSL (HTTPS),
inclusi dsniff ed ettercap. Questi strumenti funzionano solo con HTTPS, tuttavia, e quindi quando
vengono utilizzati su un'applicazione conforme a HTTPS, dovrebbero sempre visualizzare finestre
di dialogo o segnalare in altro modo un errore.
Per verificare se l'applicazione utilizza un certificato appropriato e sta eseguendo i controlli
del certificato appropriati, è necessario creare una serie di certificati con le chiavi private
corrispondenti e caricarli dinamicamente nel processo all'altro capo della conversazione. Ad
esempio, disporre di un certificato per ciascuna delle seguenti condizioni:

- Firmato da una CA non attendibile. Puoi farlo creando una CA radice casuale, magari
utilizzando Microsoft Certificate Manager o OpenSSL, e quindi utilizzandola per emettere un
certificato.

- Un certificato autofirmato. È possibile utilizzare lo strumento Microsoft selfcert.exe per eseguire questa operazione.
Peccato 23: uso improprio di PKI, in particolare SSL
353

- Non ancora valido (campo notBefore).

- Scaduto (campo notAfter).


- Il nome del soggetto (subjectName) è fasullo; ad esempio, invece di
www.example.com, utilizzare www.notanexample.com.

- Utilizzo errato della chiave; ad esempio, utilizza la firma digitale (digitalSignature) o


l'e-mail (emailProtection) ma non l'autenticazione del server (serverAuth) o
l'autenticazione del client (clientAuth), a seconda dell'estremità del canale di
comunicazione che stai testando.
- Algoritmo di firma scadente (ad esempio, signatureAlgorithm è md5RSA [noto
anche come md5WithRSAEncryption]).
- Un certificato revocato.

Per testare il controllo CRL e il supporto OSCP, puoi semplicemente osservare tutto il traffico di rete
in uscita da un'applicazione per un lungo periodo di tempo, controllando i protocolli e gli indirizzi di
destinazione rispetto a un elenco di valori noti. Se OCSP è abilitato, dovrebbe esserci un controllo OCSP
per ogni autenticazione. Se il controllo CRL è abilitato e implementato correttamente, si verificherà
periodicamente, spesso una volta alla settimana. Quindi non sorprenderti se il tuo codice esegue un
controllo CRL e non vedi traffico di rete durante l'esecuzione del controllo, perché il CRL potrebbe
essere già stato recuperato e memorizzato nella cache, rendendo non necessario un salto di rete.

ESEMPIO PECCATI
È interessante notare che, nonostante questo peccato sia estremamente diffuso soprattutto nelle
applicazioni personalizzate, ci sono pochissime voci CVE. Ma ecco un paio di esempi.

CVE-2007-4680
CFNetwork in Apple Mac OS X non è riuscito a eseguire correttamente la convalida della certificazione; un tale
errore potrebbe portare ad attacchi man-in-the-middle e spoofing del server. Poiché il bug si trovava in un
componente comunemente condiviso, CFNetwork, molte applicazioni, incluso Safari, ne erano interessate.

CVE-2008-2420
Questo è un bug interessante in Stunnel che non controlla correttamente un CRL se il supporto OCSP è abilitato, il che
potrebbe consentire a un utente malintenzionato di utilizzare un certificato revocato.
354 24 peccati capitali della sicurezza del software

FASI DI RISCATTO
Quando è ragionevole utilizzare una PKI, come SSL, fallo, assicurandoti che quanto segue sia
vero:

- Il certificato è concatenato a una CA radice valida.

- Il certificato è nel suo periodo di validità.


- Il nome host viene confrontato con il sottocampo appropriato in almeno uno dei
campi DN o nell'estensione subjectAltName X.509 v3.
- L'utilizzo della chiave del certificato è corretto: autenticazione del server o
autenticazione del client.

- Il certificato non viene revocato.

- Il programma considera il fallimento di uno qualsiasi di questi controlli come un


errore di autenticazione e si rifiuta di stabilire una connessione.

Garantire la validità del certificato


Le API hanno un supporto variabile per la validità del certificato di base. Alcuni eseguono il controllo della data e il controllo
dell'attendibilità per impostazione predefinita, mentre altri non dispongono di strutture per il supporto. La maggior parte sono
da qualche parte nel mezzo; ad esempio, fornendo servizi per entrambi, ma non facendo nessuno dei due per impostazione
predefinita.
Generalmente (ma non sempre), per eseguire la convalida su una connessione SSL, è
necessario ottenere un riferimento al certificato del server effettivo (spesso chiamato certificato
"peer" del client). Ad esempio, in Java, è possibile registrare un HandShakeCompletedListener
con un oggetto SSLSocket prima di inizializzare la connessione SSL. Il tuo ascoltatore deve
definire il seguente metodo:

public void handshakeCompleted(evento HandShakeCompletedEvent);

Quando ottieni l'oggetto evento, puoi quindi chiamare

evento.getPeerCertificates();

Questo restituisce un array di oggetti java.security.cert.Certificate. Il certificato è il tipo di base: il tipo


derivato effettivo generalmente implementa l'interfaccia java.security.cert.X509Extension, sebbene
occasionalmente possa essere un certificato precedente (java.security.cert.X509Certificate, da cui
X509Extension eredita).
Il primo certificato è il certificato foglia e il resto dei certificati forma una catena fino a
un'autorità di certificazione radice, chiamata catena di fiducia. Quando chiami questa routine,
l'API Java eseguirà alcuni controlli di base sui certificati per assicurarsi che supportino il
Peccato 23: uso improprio di PKI, in particolare SSL
355

suite di cifratura corretta, ma in realtà non convalida la catena di fiducia. Quando si adotta
questo approccio, è necessario eseguire la convalida manualmente convalidando ogni certificato
nella catena con il relativo genitore e quindi, per il certificato radice, confrontarlo con un elenco
di certificati radice noti conservati nel computer. Ad esempio, per controllare un certificato foglia
quando sai già di avere un secondo certificato radice attendibile nell'array di certificati, puoi
procedere come segue:

Tentativo {

((X509Extension)(certificato[0])).verify(certificato[1].getPublicKey()); } catch (SignatureException


e) {
/* Convalida del certificato non riuscita. */
}

Si noti che questo codice non controlla per assicurarsi che la data su ciascuno dei certificati
sia valida. In questo caso, puoi controllare il certificato peer con quanto segue:

Tentativo {

((X509Extension)(certificates[0])).checkValidity(); } catch
(CertificateExpiredException e1) {
/* Convalida del certificato non riuscita. */
} catch (CertificateNotYetValidException e2) {
/* Convalida del certificato non riuscita. */
}

Il .NET Framework offre tecniche di validità simili, ma sono infinitamente più


semplici:

Catena X509Chain = nuovo X509Chain();


chain.Build(cert);
if (chain.ChainStatus.Length > 0) {
// Si sono verificati errori
}

Un problema importante da considerare sono i certificati autofirmati. Abbiamo visto


diversi esempi di persone che confondono SSL su un canale utilizzando un certificato
autofirmato per la crittografia. Ecco perché non è una vera crittografia: un utente
malintenzionato può entrare nel mezzo della configurazione (ricorda di non fidarsi della
rete, vedi Sin 24) e presenterà il proprio certificato autofirmato al client. Se il client lo
accetta, il seguente traffico viene crittografato tra il client e l'aggressore e tra l'aggressore e
il server, ma l'aggressore vede tutto in chiaro. Se la crittografia non resiste a un attacco
man-in-the-middle, non è crittografia, è offuscamento. Se arriva l'attaccante
356 24 peccati capitali della sicurezza del software

in seguito, può interrompere la connessione e costringerla a riconnettersi, e mettersi in mezzo in quel


momento.
L'unico modo in cui un certificato autofirmato può essere utilizzato in modo sicuro è se la chiave
pubblica viene distribuita in modo sicuro fuori banda al client, il che consente quindi al codice di
verificare che il server stia utilizzando esattamente il certificato previsto. Sarà difficile gestire un
sistema del genere e non lo consigliamo (sebbene il traffico possa essere sicuro), ma tieni presente che
la parte importante è in realtà la verifica del certificato.

Convalida del nome host


Il modo migliore per controllare il nome host consiste nell'utilizzare il campo dnsName dell'estensione
subjectAltName, se disponibile. Spesso, tuttavia, i certificati memorizzeranno effettivamente l'host nel campo DN.
Ancora una volta, le API per il controllo di questi campi possono variare notevolmente.
Per continuare il nostro esempio Java JSSE, ecco come controllare l'estensione subjectAltName,
supponendo di avere un'estensione X509, mentre ricadiamo nel campo DN, in caso contrario:

private Boolean validateHost(X509Extension cert) {


Stringa s = "";
String EXPECTED_HOST = "www.example.com";
Tentativo {
/* 2.5.29.17 è l'"OID", una rappresentazione numerica standard di
* nome dell'estensione. */
s = new String(cert.getExtensionValue("2.5.29.17")); if
(s.equals(EXPECTED_HOST)) {
restituisce vero;
}
else { /* Se l'estensione è presente, ma non corrisponde a quella prevista
* value, vai sul sicuro non controllando il campo DN, which
* NON DOVREBBE avere un valore diverso. */
restituire falso;
}
} catch(CertificateParsingException e) {} /* Nessuna estensione, controlla il DN. */ if
(cert.getSubjectDN().getName().equals(EXPECTED_HOST)) {
restituisce vero;
} altro {
restituire falso;
}
}

Il codice Microsoft .NET esegue automaticamente il controllo del nome host quando si chiama
SslStream.AuthenticateAsClient, quindi non è necessario aggiungere altro codice.
Peccato 23: uso improprio di PKI, in particolare SSL
357

Verifica della revoca del certificato


Il modo più popolare per controllare la revoca è il controllo CRL, anche se il suo utilizzo non è
comune. Online Certificate Status Protocol (OCSP) ha molto da consigliare, ma il supporto CA è
stato lento a venire. Concentriamoci sui CRL. Innanzitutto, quando controlli i CRL, dovrai ottenere
il CRL appropriato trovando il punto di distribuzione CRL (CDP) che di solito si trova nel certificato.
Se esiste un CRL, di solito è accessibile tramite una richiesta FILE://, HTTP:// o LDAP://.

Ad esempio, il CRL per il certificato utilizzato da https://www.rsa.com è http://


crl.rsasecurity.com:80/RSA%20Corporate%20Server%20CA-2.crl. Come esercizio, dovresti
visualizzare il certificato utilizzato per https://www.rsa.com, trovare le informazioni sulla
CRL, quindi accedere all'URL della CRL e guardare la CRL stessa. Puoi fare tutto questo
dall'interno del browser.
Un elenco di revoca avrà una data di scadenza specificata. A meno che tu non sia davvero
preoccupato per le frequenti revoche, dovresti scaricare l'elenco delle revoche solo quando quello che
hai è scaduto. Su Windows, le chiamate del sistema operativo generalmente si occupano di questo
passaggio per te. Se ti aspetti revoche frequenti, devi decidere la frequenza con cui scaricare i CRL. In
genere, le CA aggiornano regolarmente i propri elenchi di revoche, indipendentemente dal fatto che vi
siano o meno nuovi certificati revocati. La migliore pratica qui è controllare esattamente una volta per
periodo di aggiornamento, generalmente entro 24 ore dall'aggiornamento.
Se il sistema operativo non lo fa per te, i CRL scaricati devono essere convalidati per
assicurarsi che siano adeguatamente approvati (firmati digitalmente) dalla CA. Il controllo della
revoca deve essere eseguito per ogni certificato nella catena.
In realtà, una CRL consiste semplicemente in un elenco di numeri di serie del certificato
(ricorda, ogni certificato ha un numero di serie creato dall'emittente). Per confrontare un
certificato con il CRL, confrontare il numero di serie del certificato nel certificato e confrontarlo
con l'elenco dei numeri di serie nel CRL.
Idealmente, oltre ai controlli dettagliati in questo peccato, dovresti controllare anche qualsiasi altra
estensione X.509 critica e assicurarti che non ci siano estensioni critiche che non siano comprese. Ciò
potrebbe impedirti di confondere, ad esempio, un certificato di firma del codice per un certificato SSL.
Tutto sommato, tali controlli possono essere interessanti, ma di solito non sono così critici come
sembrano.

A volte potresti non aver bisogno di tutti i controlli PKI


Che bestemmia!
Ci rendiamo conto che il precedente elenco di passaggi è complesso e certamente può
esserlo se hai bisogno di codificare queste cose da zero, ma saremo totalmente onesti: ci sono
alcuni casi in cui potresti non volere alcune delle funzionalità di sicurezza offerto da un protocollo
che utilizza una PKI, come SSL. A volte! Non stiamo dicendo che dovresti semplicemente ignorare
questi passaggi, solo che fintanto che i tuoi clienti conoscono i rischi di non eseguire alcuni dei
passaggi, allora potresti non fare alcuni passaggi. Ancora una volta, vogliamo sottolineare che
non lo consigliamo! Ma per mettere le cose in prospettiva, a volte potresti volere una crittografia
opportunistica senza alcuna autenticazione. Questo è ciò che fa Stunnel; crittografa i dati tra due
endpoint e nient'altro.
358 24 peccati capitali della sicurezza del software

A volte, potresti non volere la crittografia, ma un'autenticazione forte. Alcuni server SMTP lo
fanno per scopi di controllo dello spam; in realtà non si preoccupano molto della riservatezza,
sanno solo chi sta inviando tonnellate di e-mail.

MISURE EXTRA DIFENSIVE


Per aiutare a mitigare il furto di credenziali che porterebbe alla revoca di un certificato, potresti
prendere in considerazione l'utilizzo di hardware per l'accelerazione SSL. La maggior parte di
questi prodotti manterrà le credenziali private nell'hardware e non le fornirà al computer in
nessun caso. Ciò ostacolerà chiunque sia in grado di entrare nella macchina. Alcuni hardware
possono disporre anche di misure antimanomissione fisiche, rendendo difficile anche il lancio di
un attacco fisico.

ALTRE RISORSE
- HTTPS RFC: www.ietf.org/rfc/rfc2818.txt
- RFC 2459, "Internet X.509 Public Key Infrastructure: Certificate and CRL
Profile": www.ietf.org/rfc/rfc2459.txt
- La documentazione dell'API Java Secure Socket Extension (JSSE):
http://java.sun.com/products/jsse/
- La documentazione OpenSSL per la programmazione con SSL e TLS:
www.openssl.org/docs/ssl/ssl.html
- Centro informazioni SSL di VeriSign: www.signio.com/products-services/security-
services/ssl/ssl-information-center/
- Informazioni SslStream: http://msdn2.microsoft.com/library/
d50tfa1c(en-us,vs.80).aspx

RIEPILOGO
- Farecapire quali servizi richiedi da SSL.
- Farecapire cosa controllano le tue librerie SSL e cosa non controllano per impostazione predefinita.

- Fareassicurarsi che, prima di inviare i dati, vengano eseguiti i seguenti passaggi:

- Il certificato è concatenato a una CA radice valida.

- Il certificato è nel suo periodo di validità.


Peccato 23: uso improprio di PKI, in particolare SSL
359

- Il nome host viene confrontato con il sottocampo appropriato in almeno uno dei
campi DN o nell'estensione subjectAltName X.509 v3.
- L'utilizzo della chiave del certificato è corretto: autenticazione del server o
autenticazione del client.

- Il certificato non viene revocato.

- Farescaricare nuovi CRL una volta scaduti i CRL attuali e utilizzarli per convalidare
ulteriormente i certificati in una catena di fiducia.

- Noncontinuare il processo di autenticazione e comunicazione se la convalida del


certificato peer non riesce per qualsiasi motivo.

- Nonfare affidamento sulla libreria SSL/TLS sottostante per convalidare correttamente una
connessione, a meno che non si utilizzi HTTPS.

- Nonsoltantocontrollare il nome (ad esempio, il DN) in un certificato. Chiunque può


creare un certificato e aggiungervi il nome che desidera.
- Prendere in considerazioneutilizzando un risponditore OCSP durante la convalida dei certificati in una catena di
attendibilità per garantire che il certificato non sia stato revocato.

Potrebbero piacerti anche