/GS (controllo sicurezza buffer)

Rileva alcuni sovraccarichi del buffer che sovrascrivono l'indirizzo restituito di una funzione, l'indirizzo del gestore eccezioni o determinati tipi di parametri. La causa di un sovraccarico del buffer è una tecnica usata dagli hacker per sfruttare il codice che non impone restrizioni sulle dimensioni del buffer.

Sintassi

/GS[-]

Osservazioni:

/GS è attivato per impostazione predefinita. Se si prevede che l'applicazione non abbia esposizione alla sicurezza, usare /GS-. Per altre informazioni sull'eliminazione del rilevamento dell'overrun del buffer, vedere Safebuffers.

Controlli di sicurezza

Nelle funzioni riconosciute dal compilatore come soggetto a problemi di sovraccarico del buffer, il compilatore alloca spazio nello stack prima dell'indirizzo restituito. Nella voce della funzione lo spazio allocato viene caricato con un cookie di sicurezza calcolato una volta al caricamento del modulo. All'uscita dalla funzione e durante la rimozione dei fotogrammi nei sistemi operativi a 64 bit, viene chiamata una funzione helper per assicurarsi che il valore del cookie sia ancora lo stesso. Un valore diverso indica che potrebbe essersi verificata una sovrascrittura dello stack. Se viene rilevato un valore diverso, il processo viene terminato.

Buffer GS

Un controllo di sicurezza di sovraccarico del buffer viene eseguito su un buffer GS. Un buffer GS può essere uno di questi:

  • Una matrice di dimensioni maggiori di 4 byte, ha più di due elementi e ha un tipo di elemento che non è un tipo di puntatore.

  • Struttura di dati la cui dimensione è maggiore di 8 byte e non contiene puntatori.

  • Buffer allocato tramite la funzione _alloca .

  • Qualsiasi classe o struttura contenente un buffer GS.

Ad esempio, le istruzioni seguenti dichiarano buffer GS.

char buffer[20];
int buffer[20];
struct { int a; int b; int c; int d; } myStruct;
struct { int a; char buf[20]; };

Tuttavia, le istruzioni seguenti non dichiarano buffer GS. Le prime due dichiarazioni contengono elementi di tipo puntatore. La terza e la quarta istruzione dichiarano matrici le cui dimensioni sono troppo piccole. La quinta istruzione dichiara una struttura la cui dimensione in una piattaforma x86 non è superiore a 8 byte.

char *pBuf[20];
void *pv[20];
char buf[4];
int buf[2];
struct { int a; int b; };

L'opzione del compilatore /GS richiede l'inizializzazione del cookie di sicurezza prima dell'esecuzione di qualsiasi funzione che usa il cookie. Il cookie di sicurezza deve essere inizializzato immediatamente all'ingresso in un file EXE o DLL. Questa operazione viene eseguita automaticamente se si usano i punti di ingresso VCRuntime predefiniti: mainCRTStartup, wmainCRTStartup, WinMainCRTStartup, wWinMainCRTStartup o _DllMainCRTStartup. Se si usa un punto di ingresso alternativo, è necessario inizializzare manualmente il cookie di sicurezza chiamando __security_init_cookie.

Che cos'è protetto

L'opzione del compilatore /GS protegge gli elementi seguenti:

  • Indirizzo restituito di una chiamata di funzione.

  • Indirizzo di un gestore eccezioni per una funzione.

  • Parametri di funzione vulnerabili.

In tutte le piattaforme / GS tenta di rilevare i sovraccarichi del buffer nell'indirizzo restituito. I sovraccarichi del buffer sono più facilmente sfruttati su piattaforme come x86 e x64, che usano convenzioni di chiamata che archiviano l'indirizzo restituito di una chiamata di funzione nello stack.

In x86, se una funzione usa un gestore eccezioni, il compilatore inserisce un cookie di sicurezza per proteggere l'indirizzo del gestore eccezioni. Il cookie viene controllato durante la rimozione dei fotogrammi.

/GS protegge i parametri vulnerabili passati a una funzione. Un parametro vulnerabile è un puntatore, un riferimento C++, una struttura C (tipo POD C++) che contiene un puntatore o un buffer GS.

Un parametro vulnerabile viene allocato prima del cookie e delle variabili locali. Un sovraccarico del buffer può sovrascrivere questi parametri. E il codice nella funzione che usa questi parametri potrebbe causare un attacco prima che la funzione restituisca e venga eseguito il controllo di sicurezza. Per ridurre al minimo questo pericolo, il compilatore crea una copia dei parametri vulnerabili durante il prologo della funzione e li inserisce sotto l'area di archiviazione per eventuali buffer.

Il compilatore non esegue copie di parametri vulnerabili nelle situazioni seguenti:

  • Funzioni che non contengono un buffer GS.

  • Le ottimizzazioni (opzioni/O) non sono abilitate.

  • Funzioni con un elenco di argomenti variabile (...).

  • Funzioni contrassegnate con naked.

  • Funzioni che contengono codice assembly inline nella prima istruzione.

  • Un parametro viene usato solo in modi meno probabili da sfruttare in caso di sovraccarico del buffer.

Cosa non è protetto

L'opzione del compilatore /GS non protegge da tutti gli attacchi di sicurezza di sovraccarico del buffer. Ad esempio, se si dispone di un buffer e di una tabella virtuale in un oggetto, un sovraccarico del buffer potrebbe danneggiare la tabella virtuale.

Anche se si usa /GS, provare sempre a scrivere codice sicuro senza sovraccarichi del buffer.

Per impostare questa opzione del compilatore in Visual Studio

  1. Aprire la finestra di dialogo Pagine delle proprietà del progetto. Per informazioni dettagliate, vedere Impostare il compilatore e le proprietà di compilazione.

  2. Selezionare la pagina delle proprietà Proprietà>di configurazione C/C++>Generazione codice.

  3. Modificare la proprietà Buffer Security Check .

Per impostare l'opzione del compilatore a livello di codice

Esempio

Questo esempio esegue il sovraccarico di un buffer. In questo modo l'applicazione non riesce 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);
}

Vedi anche

Opzioni del compilatore MSVC
Sintassi della riga di comando del compilatore MSVC