Evitare sovraccarichi del buffer

Un sovraccarico del buffer è una delle fonti più comuni di rischio per la sicurezza. Un sovraccarico del buffer è essenzialmente causato dal trattamento dell'input esterno non controllato come dati attendibili. L'azione di copia di questi dati, usando operazioni come CopyMemory, strcat, strcpyo wcscpy, può creare risultati imprevisti, che consente il danneggiamento del sistema. Nel migliore dei casi, l'applicazione interromperà con un dump principale, un errore di segmentazione o una violazione di accesso. Nel peggiore dei casi, un utente malintenzionato può sfruttare il sovraccarico del buffer introducendo ed eseguendo altro codice dannoso nel processo. La copia di dati di input non controllati in un buffer basato su stack è la causa più comune di errori sfruttabili.

Avvertimento

Non usare mai funzioni stringa non associate (strcpy, strcat, sprintf, gets) nel codice sensibile alla sicurezza. Sostituirli con i relativi equivalenti delimitati (, StringCbCopy, StringCbCat) dalla StringCbPrintf o usare le varianti di suffisso C11 (_sstrcpy_s, strcat_s).

I sovraccarichi del buffer possono verificarsi in diversi modi. L'elenco seguente fornisce una breve introduzione ad alcuni tipi di situazioni di sovraccarico del buffer e offre alcune idee e risorse che consentono di evitare di creare nuovi rischi e mitigare quelli esistenti:

sovraccarico del buffer statico

Un sovraccarico del buffer statico si verifica quando un buffer, dichiarato nello stack, viene scritto in con più dati di quelli allocati per contenere. Le versioni meno evidenti di questo errore si verificano quando i dati di input utente non verificati vengono copiati direttamente in una variabile statica, causando potenziali danneggiamenti dello stack.

sovraccarico dell'heap

Gli sovraccarichi dell'heap, ad esempio i sovraccarichi del buffer statico, possono causare il danneggiamento della memoria e dello stack. Poiché gli overrun dell'heap si verificano nella memoria heap anziché nello stack, alcune persone considerano che siano meno in grado di causare gravi problemi; tuttavia, gli overrun dell'heap richiedono una reale attenzione nella programmazione e possono consentire rischi per il sistema quanto gli overrun del buffer statico.

errori di indicizzazione della matrice

Gli errori di indicizzazione delle matrici sono anche un'origine di sovraccarichi di memoria. Il controllo accurato dei limiti e la gestione degli indici consentono di evitare questo tipo di sovraccarico della memoria.

La prevenzione dei sovraccarichi del buffer riguarda principalmente la scrittura di codice valido. Verificare sempre tutti i tuoi input e gestire gli errori in modo elegante quando necessario. Per altre informazioni sulla scrittura di codice sicuro, vedere le risorse seguenti:

  • Maguire, Steve [1993], Scrivere Codice Solido, ISBN 1-55615-551-4, Microsoft Press, Redmond, Washington.
  • Howard, Michael e LeBlanc, David [2003], Writing Secure Code, 2d ed., ISBN 0-7356-1722-8, Microsoft Press, Redmond, Washington.

Nota

Queste risorse potrebbero non essere disponibili in alcune lingue e paesi.

 

La gestione sicura delle stringhe è un problema di lunga data che continua a essere risolto seguendo le procedure di programmazione consigliate e spesso usando e adattando sistemi esistenti con funzioni di gestione delle stringhe sicure. Un esempio di tale set di funzioni per la shell di Windows inizia con StringCbCat.

Mitigazioni del compilatore e del linker

Le versioni moderne del compilatore e del linker C/C++ Microsoft forniscono più livelli di difesa contro i sovraccarichi del buffer. Abilitare sempre queste protezioni nelle build di produzione:

Flag Purpose
/GS Rilevamento dell'overrun del buffer dello stack (abilitato per impostazione predefinita). Inserisce i cookie di sicurezza prima degli indirizzi di ritorno.
/sdl Abilita controlli di sicurezza aggiuntivi, tra cui il comportamento più /GS rigoroso e l'inizializzazione delle variabili.
/DYNAMICBASE Randomizzazione del layout dello spazio di indirizzamento (ASLR). Casualizza gli indirizzi di caricamento per rendere più difficile lo sfruttamento.
/NXCOMPAT Prevenzione dell'esecuzione dei dati (DEP). Contrassegna le pagine di memoria come non eseguibili.
/CETCOMPAT Intel Control-Flow Enforcement Technology (CET) per gli stack di shadow applicati dall'hardware.
/guard:cf Control Flow Guard (CFG). Convalida le destinazioni di chiamata indirette in fase di esecuzione.

Importante

Compilare con /sdl e /GS almeno per tutto il nuovo codice. Per le applicazioni critiche per la sicurezza, abilita anche /guard:cf e collega con /CETCOMPAT quando la destinazione è hardware che supporta CET.

Strumenti di analisi di runtime

Usare questi strumenti durante lo sviluppo e il test per rilevare i problemi di sicurezza della memoria prima di raggiungere la produzione:

  • AddressSanitizer (ASan): Compilare con /fsanitize=address per rilevare overflow del buffer, errori di use-after-free e altri errori di memoria in fase di esecuzione. Disponibile in Visual Studio 2019 16.9 e versioni successive.
  • Application Verifier: Rileva il danneggiamento dell'heap, l'uso improprio degli handle e altri errori di programmazione comuni.
  • Analisi statica (/analyze): l'analizzatore statico predefinito rileva sovraccarichi del buffer, variabili non inizializzate e altri problemi in fase di compilazione.