Già da alcuni anni il termine security-by-design si è diffuso nella comunità degli sviluppatori per indicare il fatto che, oltre ai requisiti funzionali, la progettazione e lo sviluppo del codice deve tenere anche in considerazione la sicurezza. La ricerca scientifica e quella industriale hanno prodotto negli ultimi decenni notevoli risultati in questa direzione. Gli strumenti a disposizione degli sviluppatori sono molteplici e si applicano alle diverse fasi dello sviluppo, dalla progettazione fino al testing.
Nonostante questo, molti sistemi vengono compromessi con attacchi che sfruttano (anche e soprattutto) vulnerabilità del software. La scarsa adozione degli strumenti che potrebbero incrementare la qualità del codice, però, non sempre è dovuta a ignoranza o pigrizia. Comprendere le ragioni di questo fenomeno è un passaggio fondamentale per affrontarlo nel modo corretto.
Indice degli argomenti
Sviluppo sicuro del software: il concetto di security-by-design
Alcune delle tecniche che fino a qualche anno fa erano note solo nella comunità scientifica sono oggi diventate parte integrante dei principali linguaggi e sistemi per lo sviluppo del software.
Un caso interessante è rappresentato dai linguaggi formali per la specifica delle proprietà del software. Questi linguaggi permettono di comparare (semi-)automaticamente le specifiche, tipicamente prodotte in fase di progettazione, con il codice sviluppato in fase di realizzazione. I benefici in termini di sicurezza sono significativi.
È noto infatti che molte falle derivano da implementazioni scorrette, cioè non rispettose delle specifiche. Esistono ambienti per la scrittura e la verifica di specifiche formali per molti dei principali linguaggi di programmazione, come ad esempio C e Java. Alcuni di questi, per esempio JML e Frama-C, sono strumenti realizzati e manutenuti da comunità di ricercatori e sviluppatori. Altri sono invece veri e propri prodotti sviluppati da importanti attori industriali, come ad esempio Spec# di Microsoft.
Proprio Microsoft ha investito risorse significative per la creazione di strumenti di verifica che aiutino gli sviluppatori a produrre codice di maggiore qualità e, quindi, più sicuro.
Gli stessi linguaggi di programmazione sono stati influenzati significativamente dalle ricerche sulla sicurezza del software. Un esempio interessante è quello dei permessi.
Storicamente, i permessi sono nati come meccanismo di gestione delle autorizzazioni per l’accesso dei programmi alle risorse sotto il controllo del sistema operativo, ad esempio i file. Nel tempo i permessi, insieme alla loro gestione, sono diventati sempre più complessi e raffinati. Ne ha esperienza chiunque usi uno smartphone. È infatti comune, dopo aver installato una nuova app, ricevere un avviso su quali permessi l’applicazione richiede per essere eseguita. È facile notare che i permessi riguardano molti aspetti, dall’uso della fotocamera fino alla possibilità di effettuare pagamenti online. La richiesta di questi permessi è parte integrante del codice dell’applicazione e gli sviluppatori devono necessariamente gestire la logica di queste autorizzazioni come parte del proprio software. Di conseguenza, tramite il controllo del sistema operativo, gli abusi nell’utilizzo dei permessi vengono individuati e impediti prima che si verifichino.
Il fenomeno del software insicuro
Queste premesse delineano uno scenario sostanzialmente ottimistico: gli strumenti per lo sviluppo del software sicuro ci sono e altri arriveranno in futuro. Tuttavia, lo stato della sicurezza dei sistemi e il numero di attacchi di cui si ha notizia non sembrano confermare questa visione.
Il numero di violazioni dei sistemi informatici è in aumento e attaccanti con sufficienti risorse e motivazioni possono minacciare molti sistemi, anche critici per i cittadini. Anche se spesso ci immaginiamo hacker dotati di conoscenze e abilità fuori dal comune, comunemente gli attacchi sfruttano vulnerabilità note, anche da parecchio tempo, che sono disseminate nel codice sorgente di scarsa qualità. Questa fenomeno è dovuto a molteplici fattori.
L’obsolescenza dei processi alla base del software difettoso
Le nuove tecnologie devono essere integrate nei processi per lo sviluppo del software. Questi processi sono spesso peculiari di ogni azienda e, in alcuni casi sono andati consolidandosi nel tempo. Integrare o modificare processi di questo tipo ha spesso un costo elevato che può essere (o essere percepito come) superiore al rischio di produrre software difettoso. Chi sviluppa le metodologie per la verifica del software tipicamente non si pone il problema dell’integrazione nei processi industriali delle aziende che potrebbero trarre i maggiori benefici dalle nuove tecniche.
Valutare l’obsolescenza dei sistemi per uno sviluppo sicuro
I processi industriali, per quanto delicati, possono essere aggiornati nel tempo. Ma cosa succede a quei sistemi che, per qualche motivo, si sono consolidati fino a uscire da un vero e proprio processo che ne adegui le caratteristiche allo scenario contemporaneo? Anche se può sembrare strano questo è un caso piuttosto comune.
Negli scorsi decenni l’informatica e l’elettronica sono penetrate rapidamente in molte catene di produzione. Oggetti puramente meccanici sono stati integrati con circuiti e relativo firmware per sfruttare la flessibilità e i bassi costi delle nuove tecnologie.
Purtroppo, in alcuni casi questi software sono stati sviluppati rapidamente per soddisfare precisi requisiti funzionali. Chi poteva prevedere che, in pochi anni, un componente meccanico originariamente isolato sarebbe diventato un dispositivo IoT collegato alla rete ed esposto ad attacchi?
Verificare sempre la molteplicità delle fonti
Quando si realizza un prodotto che include lo sviluppo di un software è importante chiedersi da dove arriva il codice. Pensiamo per esempio ad una moderna automobile. Molti dei suoi componenti meccanici includono centraline che eseguono del software, ad esempio per la gestione delle frenate. Inoltre, l’automobile monta un navigatore satellitare, magari integrato in un sistema di infotainment di bordo.
Ognuno di questi oggetti, e quindi il software che ospitano, è riconducibile a uno o più fornitori esterni all’azienda che assembla l’automobile. Ogni attore di questa catena ramificata assembla codice esistente e ne produce di nuovo senza conoscere nel dettaglio le specifiche degli altri elementi che andranno a comporre l’oggetto finale.
Il risultato è un’automobile (uno smartphone, un frigorifero…) programmata con codice scritto da vari sviluppatori con diverse affiliazioni. Qualcuno di questi potrebbe anche aver trovato su stack overflow parte del codice che controlla i freni dell’auto.
Costi occulti e limitazioni nello sviluppo del software
Gli strumenti basati sui metodi formali hanno spesso dei costi nascosti che vanno comunque tenuti in considerazione. Per esempio, molte di queste tecniche utilizzano algoritmi computazionalmente complessi che non riescono a scalare adeguatamente su sistemi di complessità reale.
Di conseguenza è possibile procedere a una verifica formale di sottosistemi di dimensione contenuta oppure di astrazioni matematiche dei sistemi reali. Nel primo caso i risultati della verifica formale devono essere interpretati considerando il contesto in cui opera il sottosistema analizzato. Nel secondo la verifica si basa su un modello matematico che deve essere opportunamente realizzato per garantirne la fedeltà rispetto all’originale.
In entrambi i casi è necessario investire risorse significative per ottenere risultati concreti. In assenza di motivazioni adeguate potrebbe essere preferibile investire su tecniche meno sofisticate ma comunque consolidate e spesso efficaci come il testing o l’ispezione manuale del codice sorgente.
Security-by-design come faro dello sviluppo sicuro del software
Alcuni dei sistemi da cui dipendiamo sono controllati da programmi scritti in modo scorretto e insicuro. Il codice di scarsa qualità, però, non sempre è il risultato di una mancanza di competenza o attenzione. In alcuni casi il contesto all’interno del quale viene prodotto un sistema favorisce la diffusione delle vulnerabilità.
Le tecniche di analisi formale del software possono dare un contributo decisivo per contrastare questo fenomeno, ma alcuni ostacoli ne rallentano o impediscono l’applicazione.
Il crescente costo degli attacchi potrebbe in futuro fornire l’incentivo decisivo per superare questo scalino tecnologico.