Article. What i write

Principi di sviluppo software sicuro: le buone prassi applicative

Pubblicato il 24 gennaio 2013
Per prevenire incidenti dovuti a bug e vulnerabilità presenti nei software è necessario attuare pratiche di sviluppo sicuro e mantenere l’analisi del codice in ogni fase del ciclo di vita dello sviluppo. Ecco l’approccio corretto e le buone prassi applicative.
Vincenzo Calabro' | Principi di sviluppo software sicuro: le buone prassi applicative
Spesso le maggiori cause di incidenti sono dovuto a bug del software: escludendo i rischi di ingegneria sociale e l’errore umano, questo significa quindi, che se non ci fossero bug, non ci sarebbero minacce alla sicurezza? O forse i sistemi possono essere sfruttati in modi non causati da bug?
Nel dubbio, è meglio prevenire attuando pratiche di sviluppo sicuro e mantenendo l’analisi del codice in ogni fase del ciclo di vita dello sviluppo.

Le debolezze del codice

La definizione (estesa e generale) di bug è che si tratta di un problema per cui il software non funziona secondo le specifiche. Domandarsi se l’assenza di bug potrebbe causare assenza di minacce, al momento non sembra avere una vera risposta, poiché i software crescono ed evolvono mediante aggiunta di nuove funzioni o librerie (aumento della superficie di attacco) e perché anche le capacità degli attaccanti evolvono mediante ricerca di modi nuovi e sofisticati di violare il codice.
A discapito della corretta operatività del codice, oltre alle vere e proprie vulnerabilità/bug (solitamente indicate con la sigla CVE seguita da un numero, n.d.r.), possono verificarsi errori umani, minacce di social engineering e algoritmi di AI che operano in modo malevolo.
In aggiunta, potrebbero essere presenti errori nelle specifiche e design del codice, o problemi di architettura software di implementazione che, se sfruttati, potrebbero inficiare il corretto operato di un software.
Senza dimenticare che diversi tipi di crittografia applicata ai dati, possono comportare al minimo problemi di performance del codice eseguibile, fino a generare veri e propri disservizi, se il codice non è opportunamente equipaggiato per gestire dati criptati.

Approccio alla sicurezza

Per ovviare alla maggior parte di questi rischi, solitamente si ricorre a pratiche di sicurezza del codice che sono “processi e pratiche coinvolti nello sviluppo di sistemi software sicuri che siano resistenti ad attacchi malevoli e vulnerabilità indesiderate. Comprende tutti i passaggi intrapresi per garantire riservatezza, integrità e disponibilità dei sistemi software durante l’intero ciclo di vita dello sviluppo software” (fonte: IEEE).
L’industria del software e il settore della sicurezza delle applicazioni hanno da tempo maturato la consapevolezza in relazione allo spostamento della sicurezza a monte del ciclo di vita del software (shift left security approach, n.d.r.), integrandola direttamente nella progettazione e nello sviluppo delle applicazioni.
Alcune aziende medie e piccole sono, invece, ancora nel bel mezzo del gap di security, ovvero non applicano pratiche di sviluppo sicuro e per questo motivo molte delle applicazioni sul mercato non sono del tutto sicure.
L’OWASP, ovvero la Open Web Application Security Project (OWASP), l’organizzazione dedicata al miglioramento della sicurezza dei software, diffonde buone prassi di sviluppo sicuro, che qui seguono in forma introduttiva, e insegna ad applicarle e a renderle parte del day-by-day.

Pratiche di Security Continuative

Una delle prime regole da adottare è l’implementazione di pratiche, strumenti e controlli di sicurezza che siano continui, ovvero svolti dall’inizio del ciclo di vita dello sviluppo software.
La continuità assicura che i prodotti siano intrinsecamente sicuri. L’integrazione di misure di sicurezza all’inizio del ciclo di vita dello sviluppo riduce drasticamente la superficie di attacco per potenziali exploit.
La filosofia alla base di questa regola è la filosofia DevSecOps che coniuga sviluppo, sicurezza e operazioni promuovendo una cultura di consapevolezza e responsabilità della sicurezza tra i team.

Security by design

Secondo questo principio la security si progetta fin dalla fase dei requisiti del software abbandonando l’uso di pensare alla sicurezza alla fine del processo, come fosse un’aggiunta eventualmente rinunciabile (e, a dire il vero, lo è stato per diversi anni ai fini del risparmio dei costi di sviluppo, n.d.r.).
L’identificazione dei requisiti di sicurezza pertinenti dovrebbe seguire di pari passo la definizione dei requisiti operativi dell’applicazione, integrando questi e quelli nel processo complessivo e della progettazione del sistema.
In aggiunta, è buona regola considerare che il sistema in sviluppo sarà soggetto a manutenzione e che gli operatori di sistema dovranno gestire in modo sicuro e persino arrestare il sistema.
Pertanto, è necessario, impegnarsi a proteggere le operazioni sviluppando principi e pratiche di “gestione operativa” che siano sicuri.

Security by default

Il significato di questo principio risiede nel fatto che l’applicazione dovrebbe essere sicura per impostazione e quindi le configurazioni predefinite devono essere le impostazioni più sicure possibili.
Questo comporta funzionalità minime capaci di proibire e/o limitare specificamente l’uso di tutte le altre funzioni, porte, protocolli e/o servizi.
In sostanza, di default, un’applicazione dovrebbe essere più restrittiva possibile, senza compromettere la cosiddetta “accettabilità psicologica” e “l’usabilità e gestibilità” del sistema (fonte: OWASP).

Principi di sicurezza nello sviluppo

Nello sviluppo di codice sicuro alcune buone prassi possono essere considerate basilari (fonte: OWASP). Ecco un breve dettaglio.

Fail Safe

È un principio di sicurezza per mantenere riservatezza, integrità e disponibilità quando viene rilevata una condizione di errore.
Queste condizioni di errore possono essere il risultato di un attacco o possono essere dovute a errori di progettazione o implementazione; in ogni caso il sistema/le applicazioni, in questi casi, dovrebbero puntare ad una impostazione predefinita che rappresenti uno stato sicuro, piuttosto che a uno stato non sicuro/non gestito.

Minimo privilegio

È un requisito che permette di assegnare ad una persona o a un processo solo il livello minimo di diritti di accesso (privilegi) necessari a completare un’operazione assegnata.
Questo diritto deve essere concesso solo per un periodo di tempo minimo necessario a completare l’operazione.
Per applicare questo principio di privilegio minimo, è necessario stabilire una corretta granularità di privilegi e permessi.
La gestione accurata dei privilegi dovrebbe impedire l’attacco di escalation verticale o orizzontale dei privilegi.

Separazione dei doveri

Rappresenta quel principio di sicurezza per cui il successo nel completamento di un singolo compito dipenda da due o più condizioni che sono insufficienti, se prese singolarmente da sole, per il completamento del compito.
Questa prassi aiuta a ridurre al minimo l’impatto di una violazione della sicurezza in caso di un tentativo di violazione riuscito.

Compartimentazione

Compartimentare l’accesso alle informazioni su una base “need-to-know” per eseguire determinate attività, contribuisce al principio del privilegio minimo e alla separazione dei doveri.

Economia del meccanismo

Spesso noto come “keep it simple”, la prassi insegna a semplificare fra le implementazioni possibili adottando quella più semplice e facilmente comprensibile, perché la probabilità di vulnerabilità aumenta con la complessità della progettazione architettonica del software e del codice e aumenta ulteriormente se è difficile seguire o rivedere il codice.

Mediazione completa

Questo accorgimento assicura che l’autorità e permesso di accesso non venga aggirata nelle richieste ad un oggetto, da parte di un soggetto/processo/servizio, verificando quindi la catena di autorizzazioni (diritti e privilegi) a ogni richiesta per l’oggetto in questione.

Accettabilità psicologica

Questo principio mira a massimizzare l’utilizzo e l’adozione della funzionalità di sicurezza nel software assicurando che la funzionalità di sicurezza sia facile da usare e allo stesso tempo trasparente per l’utente in modo che non cerchi di eludere il controllo.

Proteggere l’anello più debole

Proteggere i componenti più deboli, (codice, servizio o interfaccia), permette di minimizzare il rischio assoluto e raggiungere un livello di rischio accettabile.

Sfruttamento dei componenti esistenti

Si concentra sulla garanzia che la superficie di attacco non venga aumentata e che non vengano introdotte nuove vulnerabilità promuovendo il riutilizzo di componenti software, codice e funzionalità esistenti.
Questo dovrebbe essere garantito sia da test di regressione del codice, sia dalla adozione di patch di sicurezza dei componenti già esistenti e dalla capacità della community di vigilare sui loro eventuali bug.