Fonte: Rivista della Società Brasiliana di Informatica
Articolo di Roberto Gallo
La sicurezza di un sistema dipende sempre dalla sicurezza dei suoi componenti. Questa affermazione, sebbene apparentemente semplice e supportata dal buon senso, nasconde un universo di fattori che mettono alla prova anche i team più competenti nella progettazione, sviluppo, implementazione e manutenzione di sistemi informatici, per garantirne la sicurezza durante tutto il loro ciclo di vita.
Un esame della letteratura, dei repository di vulnerabilità noti (video CVE gestiti da MITRE) e persino dei media sull'argomento ci consente di identificare casi significativi in cui alcuni aspetti della componentizzazione del sistema hanno dato origine a problemi di sicurezza che avrebbero potuto essere evitati con una maggiore diffusione delle conoscenze sulla sicurezza tra i team di progettazione dei sistemi informatici.
Ecco alcuni esempi degni di nota:
- gli attacchi alla catena di fornitura su SolarWinds Orion e l'epidemia XZ (CVE-2024-3094) in cui questi componenti utilizzati da altre soluzioni sono stati sovvertiti,
compromettere i sistemi che li utilizzano;
- gli attacchi Downfall side-channel su CPU Intel (CVE-2023-12301), Inception su CPU AMD (CVE-2023-12302) e più recentemente l'attacco GoFetch
sotto CPU Apple Mx (2024) che consentiva la fuga di informazioni (chiavi crittografiche) tra processi (componenti) di un sistema;
- i casi di architettura inadeguata combinati con una configurazione errata dei bucket Amazon S3 che hanno dato origine a famose perdite di dati come la perdita di 1 TB da parte di Attunity nel 2019 e la perdita di 100 milioni di clienti Capital One nel 2019.
Nel corso di questo articolo esploreremo i punti in comune di diversi casi di falle nella sicurezza, apparentemente molto distinti, ma che hanno come causa principale, e quindi come risposta, l'organizzazione e l'azione coordinata dei vari team responsabili dello sviluppo, dell'acquisizione, dell'integrazione e del collaudo dei sistemi e dei componenti associati.
Alcuni problemi con la componentizzazione
La modularizzazione dei sistemi sotto forma di componenti presenta numerosi vantaggi ampiamente noti e diffusi sia in ambito accademico che industriale, in particolare la facilitazione della manutenzione e dei test, la riutilizzabilità, la riduzione dei costi e dei rischi e la scalabilità del sistema e del processo di sviluppo [1].
Questi vantaggi, tuttavia, non sfuggono ai fondamenti teorici intrinseci dell'informatica, né ai fenomeni concreti comuni che sono fonte di minacce e che, sorprendentemente, non sono incorporati nella mentalità di molti professionisti laureati in informatica. Di seguito, in forma sintetica a causa del Nel limite di spazio di questa pubblicazione, ne elenco alcuni tra i principali:
1. Il Teorema di Rice, parte fondamentale dell'informatica, afferma che qualsiasi proprietà non banale dei programmi è indecidibile. Ciò significa che non esiste un algoritmo generale in grado di decidere per qualsiasi programma e per qualsiasi possibile input se presenta una determinata proprietà comportamentale che, ad esempio, impedisce l'esecuzione di un'operazione non sicura. In pratica, ciò significa che i test di sicurezza dei programmi hanno un'assertività limitata, sono basati sui casi e necessariamente supportati da metodi euristici.
Inoltre, nonostante siano classiche e ampiamente conosciute, molti sviluppatori nutrono ancora una certa illusione che alcune tecnologie siano la "soluzione miracolosa", come le piattaforme di virtualizzazione.
- La composizione delle policy di sicurezza è molto difficile: la composizione delle singole policy di sicurezza dei componenti in una policy risultante per un sistema è un problema NP o addirittura esponenziale, anche utilizzando modelli formali con restrizioni, come le reti di Petri estese [2].
Il risultato è che, anche se esiste una descrizione formale e affidabile di cosa aspettarsi in merito alla sicurezza di un componente (una rarità), non è banale comporre tale descrizione in una politica di sicurezza per il sistema risultante.
Forse per la difficoltà, forse per l'aspetto tipicamente qualitativo dei requisiti di sicurezza, si osserva che in media sono pochi i professionisti che si affacciano sul mercato e che hanno una formazione in materia.
È anche sintomatico che la maggior parte delle licenze software affermi che “questo software non è coperto da alcuna garanzia, né è garantito che sia adatto a uno scopo particolare”;
- Modellazione ottimistica o superficiale: ricercatori e professionisti del settore informatico spesso non considerano nei loro modelli (teorici e/o mentali) che gli algoritmi e le loro implementazioni sotto forma di programmi non sono oggetti concreti, ma semplicemente istruzioni per l'esecuzione di uno o più elementi di elaborazione (CPU, MCU, GPU, NPU, FPGA), organizzati in uno o più dispositivi. Questa riduzione nella modellazione implica abitualmente ipotesi ottimistiche e irrealistiche sull'isolamento tra i componenti software e sui dati sensibili. Ad esempio, l'affermazione che un sistema implementi "protezioni a strati" quando i suoi componenti vengono eseguiti tutti sulla stessa macchina, sotto lo stesso utente, è generalmente falsa perché presenta diverse modalità di errore comuni (ovvero, un elemento che, se attaccato, viola la sicurezza di più di un componente, come il processore, il disco e il kernel).
Un altro errore che spesso si rivela fatale è quello di considerare le macchine virtuali (o container) come realmente isolate, nonostante negli ultimi anni si siano verificati innumerevoli casi di “fuga” dalle principali tecnologie.
- Astrazioni eccessive e dipendenze software: l'eccessiva astrazione delle risorse computazionali nelle API e nei framework e l'aumento vertiginoso del numero di dipendenze software facilitano simultaneamente l'inserimento intenzionale di vulnerabilità e Rendono inoltre difficile, o addirittura impossibile, per i team responsabili dell'implementazione, della manutenzione e della sicurezza mantenere aggiornati in modo adeguato la modellazione delle minacce e l'architettura del sistema.
Si sa poco del problema, ma i dati di Apache Maven [3] indicano che l'applicazione Java media nel 2022 dipendeva da circa 40 (!) librerie di terze parti. In questo contesto, una possibilità anche solo l'1,7% di contaminazione per ogni singolo componente attaccato alla supply chain comporta una probabilità complessiva di compromissione dell'applicazione pari al 50%.
D'altro canto, è ben noto nella disciplina dell'ingegneria del software che la corrosione dell'architettura [4] è un elemento che rende difficile identificare e correggere i problemi di sicurezza, rendendo lento il ciclo di mitigazione.
- Molti sviluppatori sopravvalutano la difficoltà di un attacco. Negli ultimi 25 anni ho osservato una tendenza: la maggior parte degli sviluppatori, anche quelli formati nelle nostre migliori scuole, non ha mai visto un attacco reale e pratico essere eseguito su un sistema che conosce o che ha sviluppato. Di conseguenza, molti di loro sottovalutano, se non addirittura ignorano, le minacce più comuni.
D'altro canto, quando ho lavorato su diversi casi di clienti nel corso della mia carriera professionale insieme a un team competente di ricercatori sulla sicurezza, ho potuto osservare che in circa 9 casi su 10 siamo riusciti a "vincere" e a prendere il controllo dei sistemi, a volte attaccando un singolo modulo, ma spesso abusando dell'architettura: questo tipo di esperienza spesso non viene offerto nei programmi di formazione di base per i professionisti informatici.
Questa dicotomia, dovuta alla mancanza di repertorio, ha spesso l'effetto che può essere descritto come "le persone nuove commettono errori classici".
Le migliori pratiche per la protezione dei sistemi compositi
Le migliori pratiche di sicurezza per i sistemi compositi e i loro componenti variano a seconda degli obiettivi di sicurezza e garanzia, poiché diverse metodologie e scelte ingegneristiche incidono su costi, lavoro aggiuntivo, scelte tecnologiche e tempi di esecuzione. Non si intende fornire un elenco esaustivo delle pratiche, ma solo per citarne alcuni che apparentemente ricevono pochissima attenzione nei programmi universitari.
Prima di procedere, è necessario definire alcuni termini utilizzati in questa sezione. Un obiettivo di sicurezza, chiamato anche dichiarazione di sicurezza, è una descrizione di ciò che un software, un sottosistema o il sistema stesso dichiara di fornire. Ad esempio: "Rivendicazione 1: la riservatezza del messaggio è garantita con un livello di sicurezza di 2256 contro avversari non quantistici". La certezza si riferisce al livello di certezza che una determinata affermazione sia vera. Ad esempio, l'affermazione 1 è vera con "un alto grado di probabilità" o "con prova formale".
L'esperienza pratica dimostra che progettare, implementare e mantenere componenti e sistemi con un elevato livello di sicurezza tende ad essere relativamente meno laborioso rispetto all'ottenimento di un elevato livello di garanzia, principalmente a causa degli effetti del Teorema di Rice e della Composizione delle Politiche di Sicurezza. In generale, l'elevato livello di sforzo richiesto per ottenere un elevato livello di garanzia è incompatibile con molti scenari di utilizzo, risultando fino a 3.83 volte maggiore [5] rispetto a garanzie più flessibili, come i livelli EAL 1 rispetto a EAL 7 nello standard ISO/IEC 15408 – "Criteri Comuni".
In breve, è essenziale armonizzare la criticità del caso d'uso con gli obiettivi di sicurezza e i livelli di garanzia, tenendo conto delle capacità dei team coinvolti e delle risorse disponibili. In termini di pratiche, abbiamo osservato che le seguenti sono le più efficaci:
- Base di vocabolario e metodologie: tutti i membri del team devono essere formati per utilizzare una nomenclatura comune per esprimersi in termini di obiettivi di sicurezza, minacce, vulnerabilità, controlli di sicurezza, risposta agli incidenti, ecc., utilizzando un framework documentato per la gestione del ciclo di vita sicuro dei sistemi, come Microsoft SDL o il modello SAMM;
- L'architetto delle soluzioni dovrebbe essere il responsabile della sicurezza nei progetti di piccole e medie dimensioni: in questi progetti, è importante che l'architetto delle soluzioni, o un ruolo simile, comprenda tutti i moduli e i componenti di sistema, sia in termini di codice sorgente che di architettura, e sia esperto dei principali tipi di attacchi. Si tratta di una posizione molto impegnativa, ma riduce notevolmente la necessità di formalizzare il processo di sviluppo e manutenzione del software. In generale, la formazione per questa figura professionale prevede percorsi formativi sul ciclo di vita sicuro (ad esempio MS-SDL, SAMM), tecnologie specifiche utilizzate nell'applicazione e sicurezza offensiva (ad esempio CEH, CompTIA PenTest+, ECSA/LPT);
- Progetti critici di qualsiasi dimensione richiedono formalità ed è essenziale impiegare una metodologia di garanzia, come NATO AEP-67 ENGINEERING FOR SYSTEM ASSURANCE NATO IN PROGRAMMES, che fornisce un modo per documentare e dimostrare le dichiarazioni di sicurezza e i rispettivi livelli di garanzia durante l'intero ciclo di vita della soluzione, tenendo conto di tutti i suoi componenti. Grazie alla sua capacità di coordinamento e al livello di impegno regolabile, NATO AEP-67 è stato impiegato con successo in diversi progetti di successo, oltre a servire come base per la formazione dei team [6], un argomento che verrà discusso in seguito;
- Separare il software usa e getta da quello di produzione all'origine: è necessario evitare di adottare la mentalità del software usa e getta in produzione, tipica delle fasi di prototipazione, dove l'utilizzo di versioni "nightly build" dei componenti è comunemente praticato da team di sviluppatori appassionati, sempre alla ricerca delle "ultime funzionalità". Il congelamento dei componenti in versioni "Long Term Support - LTS" svolge un ruolo fondamentale nel fornire sistemi sicuri, non solo perché garantisce la manutenibilità a lungo termine del sistema composito, ma soprattutto perché "congela" la superficie di attacco e riduce l'inserimento di difetti di sicurezza nel tempo, consentendo al team di disporre di un modello formale e/o mentale più preciso di ciò che intende proteggere.
I casi di garanzia come strumento di team building
I casi di garanzia sotto forma di NATO AEP-67 organizzano le richieste di sicurezza in modo gerarchico, come mostrato nella Figura 1. Ogni "richiesta" può essere supportata da una o più richieste intermedie ("sotto-richieste"), in modo ricorsivo.
Nell'esempio fornito, "l'affermazione A" richiede simultaneamente che le sotto-affermazioni 1 e 2 (ed eventualmente altre) siano vere affinché sia vera. A un certo punto, un'affermazione secondaria deve essere dimostrata o presunta vera, con un certo livello di certezza. Nel caso dell'affermazione secondaria 1, la sua verità viene dimostrata attraverso argomentazioni e criteri di valutazione predefiniti.

FIG. 01 | ESTRATTO DA UN CASO ASSICURATIVO, FONTE [6].
Ebbene, è proprio questa capacità (o necessità) di espressione e dettaglio nella composizione dei casi di assurance che si è dimostrata determinante nella formazione e nel miglioramento dei team che si occupano di progettazione, sviluppo e manutenzione dei sistemi, come riportato in [6]. In quel progetto, studenti laureati e laureandi di Unicamp sono stati organizzati in team con l'obiettivo di implementare un servizio di messaggistica sicuro e protetto a livello di gruppo, documentare le proprie garanzie di sicurezza e, successivamente, attaccare il sistema dell'altro team. I team sono stati così guidati durante l'intero ciclo di vita delle loro soluzioni, fornendo approfondimenti approfonditi nell'ambito della visione olistica richiesta nell'ambito della sicurezza informatica.
Nell'esperimento educativo, i casi di garanzia si sono rivelati fondamentali in almeno tre aspetti educativi: (i) hanno costretto ciascuno degli studenti a mettere in discussione le proprie ipotesi sulla sicurezza dei componenti del sistema, (ii) hanno dimostrato al team la necessità di definire e documentare policy/dichiarazioni di sicurezza semplici e precise per i componenti del sistema e (iii) hanno servito da asse comunicazione oggettiva tra i membri del team, ottimizzando gli sforzi e limitando le lacune.
Lungi dall'essere solo un guadagno teorico e un esercizio accademico, dopo l'esperimento riportato in [6], ho potuto vedere in prima persona come i casi di assurance fossero fondamentali per il miglioramento continuo e la "formazione sul campo" dei professionisti. Inoltre, tali casi sono stati utili agli stakeholder dei sistemi sviluppati poiché ora dispongono di una descrizione precisa di ciò che possono aspettarsi dai loro sistemi.
Conclusione
Progettare, implementare, ottenere e mantenere sistemi compositi sicuri è una sfida impegnativa e richiede, soprattutto, una profonda consapevolezza della situazione da parte dei team coinvolti. Nonostante i vantaggi aziendali della modularizzazione del software, la stessa organizzazione nella componentizzazione astrae molti dei percorsi pratici che gli avversari utilizzano per sferrare attacchi con successo.
Per ridurre al minimo il numero di vulnerabilità, i team di sviluppo, operativi e di sicurezza devono adottare la stessa modellazione delle minacce, lo stesso vocabolario e le stesse pratiche di sviluppo, nonché una visione olistica dei sistemi e dei loro componenti. A tal fine, metodologie e framework come Microsoft SDL, SAMM e NATO AEP-67 si sono dimostrati efficaci.
Inoltre, i team dedicati alla progettazione e allo sviluppo devono avere contatti ripetuti con i team di sicurezza per rimanere aggiornati sulle tecniche di attacco e, soprattutto, sul basso livello di sforzo richiesto per un attacco riuscito. Secondo l'autore, nulla impedisce che tutte queste conoscenze e pratiche vengano integrate nei programmi di studio universitari e post-laurea in informatica.
Riferimenti
1.
Len Bass, Paul Clements e Rick Kazman, “Software Architecture in Practice”, 4a edizione, agosto 2021.
2.
Yen, Hsu-Chun. "Sulla regolarità dei linguaggi delle reti di Petri". Atti del 13° Congresso Internazionale Annuale IEEE Phoenix
Conferenza su computer e comunicazioni (1994): 329.
3.
- M. Mir, M. Keshani e S. Proksch, “Sull'effetto della transitività e della granularità sulla propagazione della vulnerabilità nel
Maven Ecosystem", Conferenza internazionale IEEE 2023 su analisi, evoluzione e reingegnerizzazione del software (SANER), Taipa,
Macao, 2023, pp. 201-211, doi: 10.1109/SANER56733.2023.00028.
4.
- Ullah Khan, M. Munib, U. Manzoor e S. Nefti, “Analisi dei rischi a livello architettonico”, Conferenza internazionale su
Società dell'informazione (i-Society 2011), Londra, Regno Unito, 2011, pp. 231-236, doi: 10.1109/i-Society18435.2011.5978442.
5.
Kou, K., Jeong, J. e Lee, G. (2008). Definizione dei livelli di garanzia della valutazione e stima degli sforzi di valutazione per
Sistema operativo basato su ISO/IEC 19791. Conferenza internazionale sulla tecnologia della sicurezza del 2008, 176-183. https://doi.
org/10.1109/SECTECH.2008.41
6.
Gallo, R., Dahab, R. (2015). Casi di garanzia come strumento didattico per la sicurezza informatica. In: Bishop, M., Miloslavskaya, N.,
Theocharidou, M. (a cura di) Formazione sulla sicurezza informatica in tutti i settori curriculari. WISE 2015. Progressi dell'IFIP nell'Informazione
e tecnologia della comunicazione, vol. 453. Springer, Cham. https://doi.org/10.1007/978-3-319-18500-2_2
ROBERTO GALLO
È un veterano della difesa e della sicurezza informatica per applicazioni governative, di telecomunicazioni, militari, di (contro)intelligence e aziendali. Ha lavorato in ambito accademico, professionale e istituzionale. Ha conseguito un dottorato di ricerca e una laurea magistrale in Informatica con specializzazione in sicurezza informatica presso l'UNICAMP. Ha inoltre conseguito una laurea in ingegneria informatica presso la stessa università.


