Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Detecteert een bufferoverschrijding die het retouradres van een functie, het adres van de uitzonderingshandler of bepaalde typen parameters overschrijft. Het veroorzaken van een bufferoverschrijding is een techniek die door hackers wordt gebruikt om code te misbruiken die geen beperkingen voor buffergrootte afdwingt.
Syntaxis
/GS[-]
Opmerkingen
/GS is standaard ingeschakeld. Als u verwacht dat uw toepassing geen beveiligingsblootstelling heeft, gebruikt u /GS-. Zie safebuffers voor meer informatie over het onderdrukken van bufferoverschrijdingsdetectie.
Beveiligingscontroles
Op functies die door de compiler worden herkend als onderhevig aan bufferoverschrijdingsproblemen, wijst de compiler ruimte toe aan de stack vóór het retouradres. Bij functievermelding wordt de toegewezen ruimte geladen met een beveiligingscooky die eenmaal wordt berekend bij het laden van de module. Bij het afsluiten van de functie en tijdens het afwikkelen van frame op 64-bits besturingssystemen wordt een helperfunctie aangeroepen om ervoor te zorgen dat de waarde van de cookie nog steeds hetzelfde is. Een andere waarde geeft aan dat er mogelijk een overschrijf van de stack is opgetreden. Als er een andere waarde wordt gedetecteerd, wordt het proces beëindigd.
GS-buffers
Er wordt een beveiligingscontrole voor bufferoverschrijdingen uitgevoerd op een GS-buffer. Een GS-buffer kan een van de volgende zijn:
- Een matrix die groter is dan 4 bytes, heeft meer dan twee elementen en heeft een elementtype dat geen aanwijzer is.
- Een gegevensstructuur waarvan de grootte meer dan 8 bytes is en geen aanwijzers bevat.
- Een buffer die is toegewezen met behulp van de
_allocafunctie. - Elke klasse of structuur die een GS-buffer bevat.
De volgende instructies declareren bijvoorbeeld GS-buffers.
char buffer[20];
int buffer[20];
struct { int a; int b; int c; int d; } myStruct;
struct { int a; char buf[20]; };
De volgende instructies declareren echter geen GS-buffers. De eerste twee declaraties bevatten elementen van het type aanwijzer. De derde en vierde instructie declareren matrices waarvan de grootte te klein is. De vijfde instructie declareert een structuur waarvan de grootte op een x86-platform niet meer dan 8 bytes is.
char *pBuf[20];
void *pv[20];
char buf[4];
int buf[2];
struct { int a; int b; };
De beveiligingscooky initialiseren
De optie /GS-compiler vereist dat de beveiligingscooky wordt geïnitialiseerd voordat een functie die gebruikmaakt van de cookie wordt uitgevoerd. De beveiligingscooky moet onmiddellijk worden geïnitialiseerd bij het invoeren van een EXE of DLL. Dit wordt automatisch gedaan als u de standaard VCRuntime-toegangspunten gebruikt: mainCRTStartup, wmainCRTStartup, WinMainCRTStartup, wWinMainCRTStartupof _DllMainCRTStartup. Als u een alternatief toegangspunt gebruikt, moet u de beveiligingscookis handmatig initialiseren door het aan te roepen __security_init_cookie.
Wat is beveiligd
De optie /GS-compiler beveiligt de volgende items:
- Het adres van een functie-aanroep.
- Het adres van een uitzonderingshandler voor een functie.
- Kwetsbare functieparameters.
Op alle platforms probeert /GS bufferoverschrijdingen in het retouradres te detecteren. Bufferoverschrijdingen worden eenvoudiger misbruikt op platforms zoals x86 en x64, die gebruikmaken van aanroepende conventies waarmee het retouradres van een functieaanroep op de stack wordt opgeslagen.
Als een functie op x86 gebruikmaakt van een uitzonderingshandler, injecteert de compiler een beveiligingscookor om het adres van de uitzonderingshandler te beveiligen. Het koekje wordt gecontroleerd tijdens het afwikkelen van het frame.
/GS beschermt kwetsbare parameters die worden doorgegeven aan een functie. Een kwetsbare parameter is een aanwijzer, een C++-verwijzing, een C-structuur (C++ POD-type) die een aanwijzer of een GS-buffer bevat.
Een kwetsbare parameter wordt toegewezen vóór de cookie en lokale variabelen. Een bufferoverschrijding kan deze parameters overschrijven. En code in de functie die deze parameters gebruikt, kan een aanval veroorzaken voordat de functie wordt geretourneerd en de beveiligingscontrole wordt uitgevoerd. Om dit gevaar te minimaliseren, maakt de compiler een kopie van de kwetsbare parameters tijdens de functieprolog en plaatst deze onder het opslaggebied voor eventuele buffers.
De compiler maakt in de volgende situaties geen kopieën van kwetsbare parameters:
- Functies die geen GS-buffer bevatten.
- Optimalisaties (
/Oopties) zijn niet ingeschakeld. - Functies met een lijst met variabelenargumenten (...).
- Functies die zijn gemarkeerd met naakt.
- Functies die inline-assemblycode in de eerste instructie bevatten.
- Een parameter wordt alleen gebruikt op manieren die minder waarschijnlijk kunnen worden misbruikt in het geval van een bufferoverschrijding.
Wat is niet beveiligd
De optie /GS-compiler beschermt niet tegen alle beveiligingsaanvallen voor bufferoverschrijdingen. Als u bijvoorbeeld een buffer en een vtable in een object hebt, kan een bufferoverschrijding de vtable beschadigen.
Zelfs als u /GS gebruikt, probeert u altijd beveiligde code te schrijven die geen bufferoverschrijdingen heeft.
Deze compileroptie instellen in Visual Studio
- Open het dialoogvenster eigenschappenpagina's van het project. Zie C++-compiler instellen en eigenschappen bouwen in Visual Studiovoor meer informatie.
- Selecteer de eigenschappenpagina Configuratie-eigenschappen>C/C++>codegeneratie.
- Wijzig de eigenschap Bufferbeveiligingscontrole .
Deze compileroptie programmatisch instellen
- Zie BufferSecurityCheck.
Voorbeeld
In dit voorbeeld wordt een buffer overschreden. Hierdoor mislukt de toepassing tijdens runtime.
// 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);
}