La ridondanza, questa sconosciuta

Nessun meccanismo è perfetto. Un concetto che abbiamo sentito e detto in tutte le salse, e che a diversi livelli vuole dire sempre la stessa cosa: la ridondanza non è un "di più", ma una necessità. È noto in tutti i contesti in cui si parli di sicurezza, non solo informatica.
Eppure, se guardiamo alla maggioranza dei sistemi di sicurezza ICT e dei loro componenti, la ridondanza è quasi completamente assente. Ci sono in realtà alcuni contesti in cui la ridondanza è in qualche modo un concetto acquisito: è dove i problemi di sicurezza riguardano la disponibilità, quando questa si concretizza , in sostanza, in affidabilità. Ad esempio, l'utilizzo di alimentazioni ridondate, di meccanismi di hot standby dei sistemi e degli apparati, la configurazione di cammini alternativi... sono tutti meccanismi destinati ad evitare che l'utente si trovi "senza servizio" per un guasto; su questo aspetto è chiara la sensibilità dell'utente, come anche la responsabilità del "fornitore", sia esso un ISP o il servizio ICT aziendale. Non che i sistemi abbiano ovunque di questi meccanismi, ma il conto sulla convenienza o meno di queste protezioni lo capiscono più o meno tutti; se non ci sono e ci dovrebbero essere, di solito non è difficile evidenziare il problema. Si tratta in effetti di un problema di affidabilità, concetto ormai acquisito da tempo.
Tolto questo, i contesti in cui si parla effettivamente di ridondanza sono pochi. Per esempio, la "two factor authentication" è una forma di ridondanza: se un meccanismo fallisce (token rubato o password scoperta), si spera che l'altro, che è "diverso", resista. Qui si evidenzia subito un punto importante: per avere ridondanza, la resistenza di un meccanismo ad un attacco deve essere sostanzialmente indipendente dalla resistenza dell'altro. Ad esempio, probabilmente il dover inserire prima un PIN e poi una password di ridondanza ne aggiunge poca, dato che l'esposizione dell'uno in molti casi comporta l'esposizione dell'altra, e viceversa.
Dove altro vediamo ridondanza? Quasi da nessuna parte. Eppure quasi chiunque si occupi di sicurezza, a domanda, risponderà che è un aspetto fondamentale. Perché allora non si usa? La prima risposta è quella ovvia: perché la ridondanza costa. È una considerazione sulla quale c'è ben poco da dire, se non che il costo andrebbe pesato con la riduzione del rischio, e in molti casi si vedrebbe che la ridondanza serve... eppure, non credo che il problema sia tutto qui; in realtà, penso che nella maggior parte dei progetti non venga nemmeno presa in considerazione, prima ancora di porsi il problema della convenienza. C'è innanzitutto una tendenza diffusa a vedere la sicurezza in termini di funzionalità: se la funzionalità c'è, il problema è risolto. Al di là delle parole, insomma, il concetto di ridondanza è tutt'altro che assimilato. Oltretutto, l'ottica della "funzionalità" perde di vista un altro concetto fondamentale, che è quello dell'assurance, tanto importante dai tempi dell'Orange Book fino ai Common Criteria. Ma torniamo alla ridondanza.
È chiaro che un'ottica basata sulle funzionalità è facile da criticare, specialmente laddove sono note le tecniche per aggiungere ridondanza (ad esempio la famosa "difesa in profondità" delle reti), dato che è l'antitesi di quello che la teoria della sicurezza indica. Mi vorrei però concentrare su due aspetti che mi sembrano più interessanti: la finta ridondanza ed i contesti in cui l'assenza di ridondanza è data sostanzialmente per scontata.
Capita infatti ogni tanto che apparentemente ci sia della ridondanza in qualche meccanismo di sicurezza, ma ad un'analisi più attenza questa ridondanza di fatto manchi. I casi banali sono molti, ad esempio più firewall in serie, realizzati con prodotti simili e configurati dalla stessa persona: è probabile che le vulnerabilità e gli errori di configurazione dell'uno siano vulnerabilità ed errori anche nell'altro, e quindi di fatto l'indipendenza e quindi la ridondanza non ci siano. Un discorso simile vale per una configurazione in cui un firewall (senza deep content inspection) sia posto davanti a un server Web, e sul server sia installato un prodotto IPS che controlla il traffico HTTP. In questo caso, ognuno dei due strumenti affronta problemi diversi, e il fallimento dell'uno non è coperto dai meccanismi dell'altro: se il firewall fallisec ad esempio, potrebbe venire esposto un servizio di amministrazione del server, che non è coperto dall'IPS. Viceversa, un attacco a livello applicativo che l'IPS non riesca a riconoscere non è coperto dai filtri, più a basso livello, del firewall. Si tratta quindi, se vogliamo, di sinergie fra meccanismi diversi, ma non di ridondanza. Un ulteriore esempio è dato da una configurazione in cui uno switch utilizza delle VLAN per separare il traffico fra sottoreti locali e lo porta ad un firewall che filtra le comunicazioni fra le reti: anche se i due strumenti lavorassero allo stesso livello (ad esempio con un firewall che seleziona il traffico in base al tag VLAN dei pacchetti), di fatto il fallimento dello switch permetterebbe la comunicazione fra le sottoreti evitando completamente il firewall. In questo caso non c'è nè sinergia nè ridondanza: c'è semplicemente la dipendenza da due meccanismi, anziché da uno, per ottenere una funzionalità.
C'è poi il caso della dipendenza "circolare": il meccanismo A è ridondato con il  meccanismo B, che funziona solo se funziona il meccanismo C, che a sua volta dipende da A. Sembra una cosa stupida, ma si vede spesso. Per affrontare correttamente questi problemi, la domanda da porsi, per ogni meccanismo, è: cosa succede se questo meccanismo fallisce? Non serve entrare nel merito del come e perché fallisce, quella è casomai una questione di analisi del rischio. Dato per compromesso il meccanismo, si riesamina il sistema (quindi compreso il componente C di cui sopra) e si verifica che il tutto continui ad essere protetto.

È interessante notare come spesso, anziché utilizzare la ridondanza, si appesantisca il sistema con ulteriori funzionalità, ognuna delle quali si porta dietro nuove vulnerabilità.
Prendiamo come esempio il problema della compromissione della chiave privata di una Certification Authority. Il problema è naturalmente che a quel punto possono essere emessi certificati falsi, e quindi anche l'autenticità di quelli veri non è di principio più verificabile. Una soluzione possibile sarebbe stata la ridondanza: per accettare una chiave pubblica, questa deve essere stata certificata da due CA indipendenti. Su questo caso torniamo dopo. L'altra soluzione è quella di aggiungere una funzionalità in più: il servizio di timestamp per datare i certificati: quelli emessi prima della compromissione sono validi, quelli dopo no. In effetti la funzionalità non è proprio aggiunta, perché il servizio di timestamp serve comunque per datare i documenti firmati (questo è l'uso più interessante), e quindi si tratta solo di riciclarla. È un meccanismo di ridondanza? No: una volta compromessa la chiave della CA è effettivamente possibile emettere i certificati falsi; è invece un meccanismo aggiuntivo di contenimento: sono colpiti i certificati emessi dalla data della compromissione in poi (anche quelli autentici saranno invalidati), ma l'attacco non si propaga a quelli emessi prima. Vediamo quindi i limiti di questa soluzione. Il primo è il classico problema che il modello trascura, e l'implementazione fa finta di dimenticare: la compromissione di un sistema viene riconosciuta generalmente con grosso ritardo: più è di alto livello l'attacco (e probabilmente la compromissione di una CA lo è), più è difficile che venga riconosciuto. Del resto, sappiamo che questo è il problema generale della revoca dei certificati, e questo solo problema potrebbe seriamente mettere in discussione la validità del meccanismo. Inoltre, non offre ridondanza ma solo contenimento. Infine, c'è un problema, che il modello affronta correttamente ma la realtà spesso no. Perché il tutto funzioni, CA e servizio di Timestamp devo essere indipendenti. Se i due servizi sono implementati con la stessa tecnologia, e/o gestiti dalla stessa azienda e/o dalle stesse persone, è molto facile che la compromissione dell'uno coincida con la compromissione dell'altro.
Cosa offirirebbe invece la ridondanza? Se una chiave pubblica fosse firmata da due CA indipendenti, allora dalla compromissione di una sola delle due non si avrebbe nessuna conseguenza, neppure per le chiavi generate dopo la compromissione, e indipendentemente dal ritardo con cui la compromissione venisse scoperta (anzi, se ci fosse un'emissione di certificati falsi verrebbe probabilmente subito rilevata, mancando la controparte firmata dall'altra CA). I requisiti di indipendenza sarebbero chiaramente gli stessi della timestamping authority: indipendenza come tecnologie e come gestione. Funzionerebbe? È difficile dirlo: per ora gli standard, gli strumenti, le procedure e soprattutto il mercato si sono sviluppati nella direzione della singola CA, glissando elegantemente sul problema, sempre incombente, del mancato riconoscimento della compromissione. Naturalmente la ridondanza potrebbe essere vista ad un altro livello, ovvero: ridondanza dei meccanismi utilizzati per la protezione della CA. Questo approccio ha vantaggi e svantaggi, ma quello che mi sembra importante notare è che si tratta di livelli diversi: una è una ridondanza a livello di modello (due CA), l'altra a livello implementativo. Personalmente trovo che sia sempre più pericoloso "correggere" a livello implementativo un modello debole; come minimo, la complessità nella definizione e nel passaggio delle specifiche, nella rilevazione dei componenti da considerare, e la prospettiva stessa con cui può essere fatta un'analisi del rischio, sono molto più soggetti a errori e dimenticanze quando si parte da un modello (quindi da un progetto) debole per poi correggerlo nell'implementazione. E questo è un altro punto importante: la ridondanza non è solo un problema di implementazione, dovrebbe essere quanto meno presa in considerazione a tutti i livelli, salvo poi decidere eventualmente a quale livello è opportuno implementarla.
Manca ancora un tassello: cosa succede se viene compromessa la timestamping authority? Succede che anche se i certificati rimangono validi, viene messa in discussione la validità dei documenti firmati. In un contesto in cui la firma elettronica è la funzione principale del certificato, di fatto l'effetto è grave quanto la compromissione della CA, se non di più. Soluzioni attuali? Nessuna. Soluzioni possibili? Manco a dirlo, la ridondanza del servizio.
Dove sarebbe quindi utile la ridondanza? È naturalmente una questione di rischio. La ridondanza costa, e quindi ha senso usarla dove il rischio è elevato, ad esempio dove la probabilità di fallimento del meccanismo è elevata. Prodotti come Sybari fanno proprio questo: in un contesto in cui i fallimenti del singolo scan engine sono un problema relativamente frequente, l'uso di diversi motori di fonti indipendenti riduce il rischio che un virus superi le difese.
La ridondanza è però importante anche in quelle situazioni in cui la probabilità è bassa ma l'impatto è molto alto. Sono quelle situazioni fastidiose alle quali si pensa e si smette subito di pensare, le "catastrofi che in fondo non succedono". È un po' il problema della business continuity: la probabilità della catastrofe è bassa ma l'impatto è alto, e troppo spesso si fa finta che il problema non ci sia (compromissione della CA? Mah, in fondo la loro sicurezza è buona, non è ancora successo niente... pensiamo ad altro). Ci sono situazioni in cui l'assenza di ridondanza è quasi data per scontata, come se determinati meccanismi fossero in qualche modo "assolutamente robusti" e non potessero, nella pratica, essere superati.
Qualche esempio, oltre alle CA? La rottura di algoritmi crittografici; anche qui, la scoperta di un attacco ad un algoritmo non avrebbe conseguenze se si utilizzassero due algoritmi (non tanto per la cifratura delle comunicazioni, dove passare ad un altro algoritmo potrebbe essere relativamente veloce, quanto per la protezione di dati e documenti da conservare per lungo tempo) purché il meccanismo ridondante sia costituito da algoritmi abbastanza diversi come struttura. Oppure, il comportamento scorretto di fornitori si software. O ancora, i fallimenti di componenti di protocolli, ad esempio meccanismi di autenticazione, che come è noto sono difficili e lunghi da correggere, dovendo generalmente ripercorrere il processo di standardizzazione, implementazione e distribuzione; vedi ad esempio il WEP.