KNOWLEDGE BASE

Knowledge Base
1Backup
Acronis
Antivirus
Email
Firewall
GFI Software
Mail
Monitoring
N-Able
Sicurezza
TSPlus
Diventa Autore per CoreTech | Scopri di più

Vai al Video

Sviluppare in sicurezza: strumenti e best practices

Nello sviluppo di codice e applicazioni, la vulnerabilità è sempre in agguato e, come dimostrano esempi sfortunatamente celebri, se non si seguono le buone regole è probabile lasciare back-door, vulnerabilità ed anche utilizzare in maniera poco sicura toolchain di sviluppo automatico.

Banner

L’aspetto e le best practices legate allo sviluppo di software che tengono conto della sicurezza del software stesso sono ormai di fondamentale importanza per qualunque progetto, si tratti di un’applicazione desktop, di un'applicazione mobile, di un servizio o di una grossa applicazione su cloud. Oggi non si può fare a meno di pensare alla sicurezza come un requisito di progetto.

In questo tutorial verrà affrontata la tematica della gestione dello sviluppo sicuro, quindi come come approcciarsi allo sviluppo sicuro.

Faremo una breve introduzione su quelli che sono i costi sostenuti dagli addetti ai lavori e dai comuni utenti per problemi e vulnerabilità del software, dopodiché entreremo nel vivo dell'argomento esponendo i processi di sviluppo del software e faremo qualche esempio di tecnica semplice da implementare per raggiungere l’obiettivo dello sviluppo sicuro.

Sviluppo sicuro - Il programma Bug Hunting di Google

Partiamo dai costi per danni generali causati da attività illecite sui sistemi informatici a vario titolo, come perdite di dati, attacchi hacker, sottrazioni di dati dovute allo sfruttamento di bug nello Stack Bluetooth di Android, per esempio. Ebbene, l’ammontare è una cifra stratosferica, perché una ricerca di Forbes parla di circa 2,9 milioni di dollari, al minuto; moltiplicata per tutti i minuti che ci sono in un anno, viene fuori una cifra stratosferica.

Questo fa capire perché la spesa di importanti compagnie come ad esempio Google, che nel 2020 ha pagato dei Bug Hunter, ossia degli operatori di sicurezza, una somma complessiva di 6,7 milioni di dollari in ricompense, nell’ambito del programma di Bug Hunting; come mostra il grafico nell’immagine seguente, questa spesa è in crescente aumento dal 2015, anno di avvio del programma.

Il  programma funziona così: un ricercatore di sicurezza che scopra una vulnerabilità di sicurezza in uno dei prodotti Google, la può notificare a “Big G” e in base alla gravità del problema segnalato riceve una ricompensa in denaro.

Il numero è significativo perché fa capire quante vulnerabilità di sicurezza sono state scoperte. La curva del grafico fa capire come la spesa sia aumentata nel corso degli anni e questo suggerisce due cose: da una parte il fatto che ci sono sempre più ricercatori di sicurezza impegnati attivamente in queste attività e dall’altra che se giganti come Google investono in programmi del genere, l’aspetto sicurezza è fondamentale fin dallo sviluppo. Infatti non è pensabile lanciare un prodotto e aspettare che emergano i bug per correggerli al bisogno: bisogna lavorare dall’inizio in quella direzione.

Poi magari anche in un programma ben fatto c'è una vulnerabilità che è sfuggita e quindi bisogna fare un minimo di auto di autocheck interno per capire quali sono le vulnerabilità cui si va incontro e ripararle prima di mettere in produzione qualcosa.

Quindi è fondamentale adottare l’approccio ottimale, perché quando parliamo di sicurezza del software non dobbiamo pensare al codice, alla vulnerabilità, ma in generale vi sono altri ambiti che dobbiamo proteggere, a cominciare dalla propria organizzazione: esemplare è stato il caso di Solarwinds, dove non è stato tanto il codice di per sé che ha creato dei problemi, ma l'infrastruttura che lo gestiva. Analogo discorso si applica al Phishing, dove l'anello debole della catena sono le persone.

Banner

Software Development Life Cycle (SDLC)

L'approccio da adottare deve essere di ampio spettro e deve coinvolgere l'intera organizzazione; deve inoltre partire dal considerare che nello sviluppo software si entra nell'ambito di Ingegneria del software e quindi il software va visto come un prodotto che sia il frutto di un processo industriale.

Banner

In Italia molte aziende sviluppano software in-house con criteri artigianali: magari sviluppano un software senza curare troppo l’aspetto della sicurezza perché è ad uso interno, ma poi se lo distribuiscono scoprono vulnerabilità; a quel punto è sicuramente molto peggio che iniziare già a predisporre la sicurezza dal primo passo dello sviluppo.

Invece in un processo industriale, il prodotto è frutto di un processo strutturato, con procedure e regole atte a garantire quantomeno le basi della sicurezza.

Banner

In questo contesto si colloca l’SDLC, ossia Software Development Life Cycle, che significa ciclo di vita dello sviluppo software: questo ciclo deve avere come presupposto la sicurezza.  

Banner

Piccole e medie imprese che magari sviluppano software lo fanno con criteri esclusivamente artigianali: prendono uno sviluppatore che magari è anche agli inizi della carriera e sviluppa con i suoi metodi ed alla fine si arriva ad avere un blocco di software fatto da più persone magari con una diversa esperienza, ma poi andare a mettere in sicurezza un software fatto e completo, pieno di vulnerabilità è sicuramente molto peggio che iniziare già a predisporre la sicurezza su un progetto nuovo.

Come mostra l’immagine seguente, il ciclo SDLC parte dall’elenco dei requisiti e dalla progettazione, per approdare allo sviluppo, al test e alla distribuzione; a monte di questo processo, in un prodotto software che si rispetti dev’esserci però una serie di passaggi come l’assesment dei rischi, la creazione di un modello che simuli le possibili minacce, l’analisi statica, il test e l’eventuale correzione, quindi la creazione di una configurazione di sicurezza del software.  

Quindi non è pensabile concepire un software da modificare in corso d’opera magari su richiesta tardiva del cliente, perché la semplice aggiunta di una funzione potrebbe vanificare la progettazione  fatta a monte: per esempio una casella o un pulsante che esegue un’operazione su database in un sito web, per quanto apparentemente normale potrebbe aggiungere un rischio che nella fase di Risk Assesment non è stata considerata, andando a costituire una potenziale vulnerabilità. 

Rendere sicuro il ciclo di vita dello sviluppo

Spesso la sicurezza dello sviluppo viene completamente ignorata finché non si verifica un incidente che causa danni non trascurabili.

Un altro aspetto che tipicamente viene ignorato, tranne che in alcuni ambiti specifici, è quello della stabilità: se un’applicazione non è mission-critical, ossia non determina il funzionamento di un’azienda o di un processo di sicurezza, spesso non ci si preoccupa di scrivere il programma in modo che non vada frequentemente in crash. 

L’abitudine, quindi, è che se il cliente non lo esige per contratto, quello della sicurezza è un tema trascurato o almeno lo è stato sino a poco tempo fa; oggi, regole scritte a livello europeo ed anche necessità sorte dal fatto che i rischi sono aumentati (la cosiddetta “superficie d’attacco” è aumentata) dal fatto di essere ormai tutti connessi (anche i software tra di loro sono interconnessi) stanno cambiando la mentalità e spingendo verso il concetto di Secure SDLC.

Un esempio di come la sicurezza potrebbe essere compromessa lo si vede in software molto diffusi, sviluppati da grandi realtà, dove un’applicazione “blindatissima” sotto l’aspetto della sicurezza diventa vulnerabile perché supporta un plugin esterno sviluppato da una software house esterna che avendo accesso “interno” introduce una back door. Se c'è una via d'accesso, a quel punto diventa difficile capire anche di chi sono le colpe in caso di vulnerabilità e conseguente incidente informatico.

Altro esempio è nelle applicazioni software: oggi se ne utilizzano tantissime e magari un sistema sicuro può essere penetrato proprio attaccando la più debole di esse; anche per questo è bene codificare quali processi vengono utilizzati maggiormente dal sistema.

Questo è uno degli aspetti suggeriti dal NIST nel framework per un Secure SDLC che riassume tutti gli aspetti esposti in questo capitolo (immagine seguente); ci riferiamo al PS-Protect the software. Tale framework fissa uno standard oggi molto utile e utilizzato.

Il framework definisce quattro principali linee d’azione, delle quali una sola si riferisce allo sviluppo del software in quanto tale: gli altri aspetti ineriscono a comportamenti da adottare nell’ambiente di lavoro.

Il primo è la preparazione dell’organizzazione e la formazione del personale finalizzata a far utilizzare applicazioni e sistemi IT in maniera consapevole, ma ciò non significa lato utente, evitando trappole come il Phishing, l’apertura di e-mail sospette ecc. Significa che gli sviluppatori devono essere formati avendo la sicurezza come punto chiave del proprio lavoro e che devono costantemente aggiornati in modo da saper identificare le aree dove si possono sviluppare vulnerabilità. Inoltre serve una gerarchia, ossia stabilire delle responsabilità e ruoli differenti: ci deve essere chi scrive, chi revisiona il codice, chi approva le modifiche ecc. Non è più possibile avere ua figura che si occupi di tutto 

Il secondo livello, PS-Protect the software, implica il proteggere tutta l’infrastruttura che consente di scrivere i sorgenti, fare le build, eseguire il deployment e via di seguito, perché magari si scrive un’applicazione sicura ma poi un attaccante penetra nei server e vi inietta codice malevolo capace di alterare del codice che pure era nato sicuro.

Importante è anche la terza area, che concretamente significa adottare strumenti che aiutino a garantire la qualità del prodotto e la sua sicurezza: progettare un software che faccia una certa cosa è relativamente semplice, ma scriverne uno che faccia solo quella e non si presti ad essere sfruttato per fare ciò che non dovrebbe e che causi dei danni a causa di vulnerabilità, è meno facile. Bisogna quindi cercare di sviluppare usando tool che semplifichino il controllo sul software ed anche appoggiarsi a strumenti e piattaforme di qualità, dove si è certi che non ci siano back door o codice malevolo che inevitabilmente ci si porta dentro e nemmeno si ipotizza, perché ci si fida del produttore.

Banner

Ultimo ma non meno importante è conoscere bene il prodotto e redigere dei piani di intervento che tengano conto di quei rischi che non possono essere eliminati: insomma, occorre pensare, quando si scrive del codice e lo si sviluppa, a quali problemi potrebbe essere esposto, quindi preparare le contromisure. Ma occorre anche dotarsi degli strumenti giusti per fare debug, per avere dei log in caso di anomalia e accelerare il processo di remediation in caso di incidente.

Best Practices - Gestione delle credenziali

Sviluppo sicuro non significa esclusivamente adottare strategie di programmazione, deployment e conservazione, ma anche identificare, stabilire e regolamentare l’accesso all’ambiente di sviluppo, ai codici sorgente e via di seguito. In breve, è fondamentale regolamentare i privilegi di accesso al codice e alle risorse coinvolte nel ciclo di sviluppo, perché il codice è un asset strategico e come tale va protetto adottando alcune best practice che possono così essere riassunte:

  • le credenziali di accesso al codebase devono consentire l’identificazione sia dell’utente che della macchina da cui sta operando;
  • qualora nello sviluppo si adottino soluzioni on-premise, l’accesso alle relative macchine va definito adeguatamente (le credenziali di accesso a Gitlab hanno poco senso se le conoscono tutti coloro che operano in azienda);
  • gli eventuali sistemi di backup adottati dovrebbero ricorrere alla cifratura dei dati ed offrire soluzioni anti-tampering; questo perché un attaccante potrebbe corrompere i backup conoscendo e potendo entrare nel server di backup (anche remoto) dell’azienda e poi approfittare di un ripristino effettuato da questi per introdurre codice malevolo nel sistema usato per lo sviluppo;
  • i server e le workstation coinvolti nel processo di sviluppo non dovrebbero essere accessibili dall’esterno, ovvero da Internet o accessi remoti di vario genere, pertanto non andrebbero collegati a un router o modem.

Inoltre è opportuno definire quali risorse e quali operazioni possono essere accessibili da parte di chi, in azienda: per esempio il titolare dell’azienda di sviluppo non è che per il solo fatto d’esserlo debba avere accesso al sistema e magari può accedere solo per vedere il lavoro fatto ma senza potervi apportare modifiche né aprire programmi estranei che potrebbero far entrare minacce.

Banner

Best Practices - Formazione del personale

La formazione è importante da tutti i punti di vista, non solo a livello informatico e dello studio di nuove soluzioni, ma anche a livello proprio informativo, ossia continuare a informarsi sulle vulnerabilità conosciute e sulle varie notizie che le riguardano, perché magari si utilizza un sistema dove si è scoperto che c'è un bug ma il personale addetto allo sviluppo non lo sa e si espone al rischio.

Prima di iniziare uno sviluppo, conviene sempre cercare notizie sulle vulnerabilità che riguardano il codice, i tool utilizzati e le macchine target.

Se il sistema utilizzato per lo sviluppo utilizza applicativi che hanno vulnerabilità note bisogna aggiornarli o sostituirli.

Banner

Quindi è importante informarsi su ciò che accade intorno a noi e su quello che viene scoperto relativamente agli applicativi, augli strumenti che utilizziamo e via di seguito.

In quest’ottica è opportunoe fondamentale prevedere e programmare attività periodiche di formazione e aggiornamento degli addetti allo sviluppo.

Best Practices - Revisione del codice

In generale uno degli strumenti più importanti è la revisione, perché il codice non può semplicemente essere scritto, testato dalla stessa persona e immediatamente integrato. Infatti è fondamentale una revisione, preferibilmente operata da un soggetto diverso da quello che ha scritto il codice, in quanto far vedere il proprio lavoro a un altro evidenzia maggiormente anomalie e cose che possono sfuggire a chi si è arrovellato la mente nella scrittura di un programma. Tipicamente chi legge il lavoro di un altro ha la mente più libera perché non conoscendo il prodotto è più portato a rilevare le anomalie.

In un’azienda di sviluppo di codice è quindi importante avere una figura che revisiona il codice scritto dai programmatori, che può essere un altro programmatore che si scambia il codice con un collega, ovvero una persona dedicata alla revisione.

La revisione incrociata fra sviluppatori permette non solo di utilizzare al meglio le risorse umane aziendali, ma anche di crescere la conoscenza dei singoli individui, in quando leggere un codice scritto da un altro permette magari di apprendere o approfondire tecniche di programmazione che non si conoscevano fino a poco prima, quindi di scambiarsi le competenze fra sviluppatori.

La revisione si esegue in due momenti diversi e si può svolgere secondo due modalità:

  • Change-based code review, dove l’approvazione delle modifiche è subordinata alla revisione da parte di un manteiner;
  • Scheduled code review, dove l’attività di revisione coinvolge l’intera squadra e viene effettuata a intervalli di tempo programmati.

Esiste anche una terza modalità, che si basa sulla figura di un manteiner, che è una persona cui è delegato il compito di valutare ed eventualmente approvare le modifiche al codice emerse durante la code-review eseguita dagli altri.

Questo aspetto diventa determinante nei progetti open source, dove la collaborazione degli appartenenti alla community è ben accetta ma dev’essere controllata, giacché non solo non tutti i partecipanti possono sviluppare codice di qualità, ma addirittura qualcuno può infiltrarsi e creare dei commit che introducono delle back door.

Comunque un responsabile delle revisioni deve sempre esistere, almeno nelle aziende che sviluppano applicazioni dove la sicurezza è un fattore imprescindibile.

La revisione del codice dev’essere un’operazione per la quale, nel progetto, è stato previsto del tempo e non può essere un’operazione fatta in fretta o rubando tempo e risorse alla routine: dev’essere considerata una parte dello sviluppo e come tale meritevole di una porzione del tempo complessivo richiesto dalla realizzazione di un progetto. Ci si deve prendere tutto il tempo che occorre.

La revisione incrociata va chiaramente configurata come un’operazione costruttiva e non deve in alcun modo generare problemi fra le risorse umane, magari perché considerata come terreno di competizione tra sviluppatori: dev’essere un momento di confronto, non di competizione.

Strumenti di test di sicurezza

Tornando un momento sulla protezione del codice nel caso venga salvato e condiviso in dei repository, va precisato che sebbene Git ( GitLab e GitHub) sia sicuro sotto l’aspetto drittografico, nel senso che non è possibile alterare dei commit presenti all’interno dei repositori, almeno da parte di utenti non abilitati, chiunque abbia accesso ai repository potrebbe, invece, inviare dei propri commit spacciandosi per un membro del team di sviluppo. 

Banner

Per evitare che ciò accada (ed è già accaduto qualcosa del genere con lo sviluppo di PHP) è possibile imporre che ciascun membro del team di sviluppo firmi con una firma crittografata le proprie revisioni; questo può essere ottenuto adottando le firme CPG, grazie alle quali l’identità dell’autore di un commit viene garantita.

Questo strumento è nato per firmare le e-mail e in generale permette di certificare l’identità delle persone attraverso certificati rilasciati da autorità riconosciute.

Banner

Lo strumento di firma CPG è integrato in applicazioni quali GitLab e GitHub, che possono quindi riconoscere l’autenticità della firma e mostrare il risultato del check in ogni istante. Per esempio su GitHub, se si fa un commit firmato con strumento CPG, chi vi accede vedrà apparire qualcosa come quello proposto nell’immagine seguente, che mostra la conferma che il commit su GitHub è stato firmato con una firma verificata.

La firma in GitLab è particolarmente importante perché l’applicazione permette di impostare una serie di regole chiamate Push Rules (immagine seguente) che permettono di stabilire le condizioni a cui avvengono i push (ovvero limitano questi ultimi) da parte degli utenti del team.

Banner

Da qui è possibile, ad esempio, flaggare la voce Reject unsigned commits per rifiutare i commit non firmati.

Banner

Banner

Se qualcuno tenta di inserire commit non firmati crittograficamente, al manteiner viene notificato che è avvenuto tale tentativo e da parte di quale utente, così da smascherare tentativi di effrazione del meccanismo di sicurezza, magari da parte di attaccanti che si fingono utenti del team.

Strumenti di Analisi Statica e Dinamica

Un altro aspetto fondamentale della revisione del codice che sviluppiamo è l’utilizzo di strumenti di analisi automatica statica (SAST=Static Application Security Testing) e dinamica (DAST=Dynamic Application Security Testing):

Banner

  • per analisi statica s’intende che viene esaminato il codice riga per riga alla ricerca di errori di programmazione o pattern noti; questo tipo sdi analisi non riesce, però, a rilevare errori che appaiono nell’esecuzione del codice (ad esempio può dare errori nel caso si utilizzi una funzione che non fa il boundary check della memoria);
  • l’analisi dinamica è invece svolta eseguendo il codice

L’immagine seguente schematizza a sinistra un’analisi statica e a destra una dinamica.

Banner

Banner

Ci sono tante soluzioni commerciali ed open source per l’analisi statica del codice, perché il SAST deve conoscere il linguaggio nel quale è sviluppata l’applicazione da testare, ragion per cui se ne trova almeno una per ogni linguaggio. Alcune soluzioni SAST sono integrate in applicazioni, come ad esempio quelle basate su repository (GitHub) o di continuous integration che analizzano il codice nel momento in cui viene fatto un push, fornendo alert nel caso sia trovato un errore.

Tali strumenti aiutano tanto, anche perché non bisogna fare nulla: il sistema, una volta impostato il tutto, automatico ci avvisa inviando delle notifiche quando trova degli errori di codice, quindi degli errori di sintassi o comunque delle possibili vulnerabilità.

Per quanto riguarda l’analisi dinamica, gli strumenti (DAST) corrispondenti sono sempre automatici ma permettono di eseguire l’analisi a run-time e scoprire errori che formalmente non riultano ma si manifestano in esecuzione.

Questo tipo di analisi non richiede l’accesso al codice ma interagisce con esso durante l’esecuzione, alla ricerca di vulnerabilità note. Per esempio nel caso di un’applicazione web, si può trattare di strumenti che simulano l’azione dell’utente che apre pagine web, compila dei form, aziona link e pulsanti, introduce elementi come quando si caricano immagini e documenti.

L’analisi dinamica quindi non richiede che il tool conosca il linguaggio né che apra il codice, ma semplicemente testa il comportamento dell’applicazione costruita dal codice stesso.

Le analisi servono entrambe: statica e dinamica; non ce n’è una che escluda l’altra. 

Banner

Un ulteriore aspetto da non trascurare riguarda il testing in ambiente di pre-produzione, che rappresenta una best practice del buon sviluppatore: il testing di un prodotto software in uno o più ambienti di pre-produzione permette di individuare eventuali errori prima del rilascio del prodotto stesso. Tale fase viene chiamata staging e si svolge in un ambiente artefatto che è un gemello di quello di produzione (si bassa sullo stesso hardware, ambiente e sulla medesima configurazione) come se si provasse il motore di un’automobile su un prototipo in tutto e per tutto uguale all’auto che poi lo utilizzerà in produzione. Questo permette di avare informazioni sul comportamento del prodotto nell’ambiente target, senza correre i rischi che si correrebbero in caso di vulnerabilità durante il normale utilizzo.

Nel caso in cui l’ambiente di esecuzione sia fornito dal committente dell’applicazione (sia essa una app mobile o desktop) l’ambiente di staging non può essere definito univocamente; in un caso del genere si ricorre ad ambienti di testing le cui caratteristiche variano ad ogni esecuzione del test. Questo perché, soprattutto nelle applicazioni mobile, esiste una gran varietà di versioni di sistema operativo (per esempio Android) e di configurazioni, con varie app.

Concludiamo con una curiosità: l’analisi dinamica è una tecnica nata per verificare la stabilità delle applicazioni e poi estesa, per i suoi vantaggi, al test della sicurezza e alla ricerca di bug.

Banner