Linee guida per la scrittura di codice protetto
Aggiornamento: novembre 2007
Nelle linee guida riportate di seguito vengono illustrate alcune tecniche per la scrittura di codice protetto.
Operazioni necessarie
Utilizzare strumenti di analisi del codice.
In Visual Studio Team System Development Edition sono disponibili strumenti di analisi del codice che aumentano notevolmente le probabilità di trovare errori di sicurezza nel codice, con evidenti vantaggi in termini di efficienza e facilità d'uso. Per ulteriori informazioni, vedere Rilevamento e correzione di errori del codice C/C++ e Rilevamento e correzione degli errori del codice gestito.
Effettuare una revisione per rilevare problemi di sicurezza.
L'obiettivo di questo tipo di revisione è aumentare la sicurezza dei prodotti già rilasciati attraverso patch e correzioni o garantire che vengano forniti solo prodotti caratterizzati dalla massima sicurezza possibile.
Non eseguire una revisione approssimativa del codice. Prepararsi in anticipo e partire dalla creazione di una classificazione dei rischi per evitare che i componenti del team sprechino tempo prezioso. Stabilire un ordine di priorità del codice da sottoporre alla verifica più accurata della sicurezza e degli errori di sicurezza da correggere.
Specificare in modo dettagliato gli elementi da verificare durante la revisione. Una ricerca mirata consente di identificare i problemi con maggiore facilità. Approfondire ulteriormente la ricerca se il team rileva un numero considerevole di errori di sicurezza in una determinata area in quanto essi potrebbero indicare un problema di architettura che è necessario risolvere. Se non viene rilevato alcun errore di sicurezza, è molto probabile che la revisione non sia stata effettuata correttamente.
Considerare la revisione per la verifica della sicurezza come parte della stabilizzazione di ogni fase di sviluppo e come una strategia di promozione più ampia della linea di prodotti stabilita dalla dirigenza.
Utilizzare un elenco di controllo per eseguire una verifica della sicurezza.
Indipendentemente dal ruolo rivestito nel team di sviluppo software, è utile disporre di un elenco di controllo da seguire per far sì che il codice e la progettazione soddisfino un livello minimo stabilito.
Convalidare tutto l'input utente.
Se l'applicazione è impostata per l'accettazione dell'input utente, direttamente o indirettamente, è necessario convalidare tale input prima di utilizzarlo. Gli utenti malintenzionati tenteranno di rendere inutilizzabile l'applicazione sviluppata modificando l'input per rappresentare dati non validi. La prima regola dell'input utente è la seguente: tutto l'input deve essere considerato non valido fino a prova contraria.
Utilizzare con cautela le espressioni regolari per convalidare l'input utente. Per espressioni complesse come gli indirizzi di posta elettronica, è facile pensare che si stia svolgendo una convalida completa anche quando in realtà non viene effettuata. Chiedere ai propri colleghi di revisionare tutte le espressioni regolari.
Convalidare in modo sicuro tutti i parametri delle API (application programming interface) esportate.
Assicurarsi che tutti i parametri delle API esportate siano validi. Verificare, ad esempio, l'input che appare uniforme ma presenta valori che superano l'intervallo accettabile, quali dimensioni del buffer troppo elevate. Non utilizzare le asserzioni per verificare i parametri relativi alle API esportate in quanto esse verranno rimosse nella build di rilascio.
Utilizzare le API di crittografia di Windows.
Anziché scrivere un software di crittografia personalizzato, utilizzare l'API di crittografia di Windows già disponibile. Attraverso questo tipo di API Microsoft, gli sviluppatori hanno la possibilità di concentrarsi sulla compilazione di applicazioni. È importante ricordare, infatti, che la crittografia risolve molto bene una piccola serie di problemi e viene spesso utilizzata con modalità diverse da quelle per cui è stata creata. Per ulteriori informazioni, vedere Cenni preliminari sulla crittografia in MSDN Library.
Operazioni da evitare
Sovraccarichi del buffer.
Un sovraccarico del buffer statico si verifica quanto un buffer dichiarato sullo stack viene sovrascritto mediante la copia di dati più grandi del buffer stesso. Le variabili dichiarate sullo stack si trovano accanto all'indirizzo per il chiamante della funzione. I sovraccarichi del buffer possono verificarsi anche nell'heap e sono altrettanto pericolosi. La causa più frequente è il passaggio di input utente non controllato a una funzione come strcpy che comporta la sovrascrittura dell'indirizzo per la funzione da parte di un indirizzo scelto da chi esegue l'attacco. Per impedire i sovraccarichi del buffer, generalmente è sufficiente scrivere un'applicazione affidabile.
Asserzioni per controllare l'input esterno.
Le asserzioni non vengono compilate nelle versioni per la vendita. È opportuno quindi non utilizzarle per verificare gli input esterni. È necessario verificare la validità di tutti i parametri relativi a metodi e funzioni esportate, dell'intero input utente e di tutti i dati su file e socket, respingendoli se contengono errori.
Coppie di ID utente e password specificate a livello di codice (hard-coded).
Non utilizzare password specificate a livello di codice. Modificare il programma di installazione per far sì che al momento della creazione di account utente incorporati, all'amministratore vengano chieste password sicure per ogni account. In questo modo sarà possibile garantire la sicurezza dei sistemi a livello di produzione dei clienti.
L'utilizzo della crittografia risolve tutti i problemi di sicurezza.
È importante ricordare, infatti, che la crittografia risolve molto bene una piccola serie di problemi e viene spesso utilizzata con modalità diverse da quelle per cui è stata creata.
URL e percorsi file canonici.
Evitare le situazioni in cui il percorso di un file o di un URL è importante. Utilizzare ACL del file system piuttosto che regole basate su nomi di file canonici.
Operazioni consigliate
Esaminare tutti i problemi di sicurezza precedenti rilevati nell'applicazione.
Acquisire familiarità con gli errori di sicurezza commessi in passato. Il codice viene spesso scritto sulla base di modelli ricorrenti, pertanto la presenza di un errore commesso da una determinata persona in una posizione potrebbe indicare lo stesso errore commesso da altre persone in altre posizioni.
Esaminare tutti i percorsi degli errori.
Spesso il codice nei percorsi degli errori non viene sottoposto a testing in modo appropriato e non comporta la pulizia di tutti gli oggetti, ad esempio i blocchi o la memoria allocata. Esaminare con attenzione tali percorsi e, se necessario, creare test di inserimento di errori per eseguire e verificare il codice.
Operazioni non consigliate
Privilegi dell'amministratore per l'esecuzione dell'applicazione.
Le applicazioni devono essere eseguite con il livello di privilegio più basso per consentire il completamento del lavoro. Se un utente malintenzionato rileva una vulnerabilità nel sistema di sicurezza e inserisce porzioni di codice nel processo, il codice dannoso verrà eseguito con gli stessi privilegi del processo host. Se il processo viene eseguito come amministratore, il codice dannoso verrà eseguito come amministratore. Per ulteriori informazioni, vedere Developing Secure Applications in MSDN Library (informazioni in lingua inglese).