/GS (Controllo protezione buffer)
Aggiornamento: novembre 2007
Rileva i sovraccarichi del buffer che sovrascrivono l'indirizzo di ritorno, una tecnica comune utilizzata per sfruttare il codice che non attiva le restrizioni della dimensione del buffer e realizzata inserendo dei controlli della protezione nel codice compilato.
/GS[-]
Note
/GS è attiva per impostazione predefinita. Utilizzare /GS- se si prevede che l'applicazione non presenti rischi di protezione.
Per informazioni aggiuntive su /GS vedere Compiler Security Checks In Depth.
Il compilatore inserisce i controlli in funzioni con buffer di stringa locale o, su x86, in funzioni con gestione delle eccezioni. Con il termine buffer di stringa si indica una matrice i cui elementi hanno dimensioni pari a uno o due byte e in cui le dimensioni dell'intera matrice raggiungono almeno cinque byte, oppure qualsiasi buffer allocato con _alloca.
In tutte le piattaforme, il compilatore inserisce un cookie per proteggere l'indirizzo di ritorno della funzione se questa dispone di buffer di stringa locale. All'uscita della funzione e durante la rimozione del frame nei sistemi operativi a 64 bit o nei processori x86, viene verificata la presenza nel cookie di funzioni con qualche forma di gestione delle eccezioni. Nei processori x86, il compilatore inserisce anche un cookie per proteggere l'indirizzo del gestore eccezioni della funzione. La verifica relativa a questo cookie viene effettuata durante la rimozione del frame.
Con l'opzione /GS si tenta principalmente di rilevare i sovraccarichi del buffer diretti nell'indirizzo di ritorno. I sovraccarichi del buffer vengono sfruttati più facilmente in computer con convenzioni di chiamata che archiviano l'indirizzo di ritorno delle chiamate di funzione sullo stack. I processori x86, ad esempio, utilizzano convenzioni di chiamata di questo tipo.
Sulle funzioni ritenute soggette a problemi di sovraccarico del buffer, il compilatore allocherà spazio sullo stack prima dell'indirizzo di ritorno. All'ingresso della funzione lo spazio allocato viene caricato con un cookie di protezione calcolato una volta al caricamento del modulo. Pertanto, all'uscita della funzione, verrà chiamata una funzione di supporto per garantire che il valore del cookie sia ancora lo stesso.
Se il valore non è lo stesso, è possibile che lo stack sia stato sovrascritto e il processo verrà terminato. Prima di Visual C++ 2005 veniva visualizzata una finestra di dialogo che segnalava la sovrascrittura dello stack.
L'opzione /GS protegge inoltre dai parametri vulnerabili passati in una funzione. Un parametro vulnerabile è un puntatore, un riferimento C++ o una struttura C di tipo POD C++ che contiene un puntatore, un buffer di stringa o un riferimento C++.
Un parametro vulnerabile viene allocato prima del cookie e delle variabili locali. Un sovraccarico del buffer può sovrascrivere questi parametri. Il codice nella funzione che utilizza questi parametri può provocare un attacco prima che la funzione restituisca un risultato, aggirando in questo modo i controlli di protezione. Per contenere i rischi, il compilatore creerà una copia dei parametri vulnerabili nel corso del prologo della funzione e li inserirà sotto l'area di archiviazione di tutti i buffer.
Il compilatore non è in grado di proteggere dai parametri vulnerabili nelle situazioni riportate di seguito:
Funzioni che non contengono un buffer.
Ottimizzazioni (Opzioni /O (Ottimizza codice)) non attivate.
Funzioni con un elenco di argomenti variabili (...).
Funzioni contrassegnate con naked (C++).
Funzioni che contengono codice assembly inline nella prima istruzione.
Un parametro viene utilizzato esclusivamente con modalità che potrebbero essere meno sfruttabili nel caso di un sovraccarico del buffer.
/GSrichiede l'inizializzazione del cookie di sicurezza, che deve essere effettuata prima dell'esecuzione di qualsiasi funzione che lo utilizza. Il cookie di sicurezza deve essere inizializzato all'ingresso in un file EXE o in una DLL. Questa operazione viene eseguita automaticamente quando si utilizzano i punti di ingresso CRT predefiniti (mainCRTStartup, wmainCRTStartup, WinMainCRTStartup, wWinMainCRTStartup o _DllMainCRTStartup), mentre dovrà essere effettuata manualmente, tramite una chiamata a __security_init_cookie, se si utilizza un diverso punto di ingresso.
L'opzione /GS è supportata per le funzioni gestite durante la compilazione con /clr (Compilazione Common Language Runtime).
L'opzione /GS non protegge da tutti gli attacchi alla protezione dei sovraccarichi del buffer. Se, ad esempio, in un oggetto sono presenti un buffer e una vtable, il sovraccarico del buffer potrebbe danneggiare la vtable e provocare un attacco.
Anche se si utilizza /GS, è consigliabile cercare di scrivere codice protetto. Assicurarsi, pertanto, che il codice non presenti sovraccarichi del buffer. L'opzione /GS è in grado di proteggere l'applicazione dai sovraccarichi del buffer ancora presenti nel codice.
Per impostare l'opzione del compilatore nell'ambiente di sviluppo di Visual Studio
Aprire la finestra di dialogo Pagine delle proprietà del progetto. Per informazioni dettagliate, vedere Procedura: aprire le pagine delle proprietà dei progetti.
Fare clic sulla cartella C/C++.
Fare clic sulla pagina delle proprietà Generazione codice.
Modificare la proprietà Controllo protezione buffer.
Per impostare l'opzione del compilatore a livello di codice
- Vedere BufferSecurityCheck.
Esempio
Nell'esempio riportato di seguito si verifica il sovraccarico di un buffer, con conseguente errore dell'applicazione in fase di esecuzione.
// compile with: /c /W1
#include <cstring>
#include <stdlib.h>
#pragma warning(disable : 4996) // for strcpy use
// Vulnerable function
void vulnerable(const char *str) {
char buffer[10];
strcpy(buffer, str); // overrun buffer !!!
// use a secure CRT function to help prevent buffer overruns
// truncate string to fit a 10 byte buffer
// strncpy_s(buffer, _countof(buffer), str, _TRUNCATE);
}
int main() {
// declare buffer that is bigger than expected
char large_buffer[] = "This string is longer than 10 characters!!";
vulnerable(large_buffer);
}