/GS(버퍼 보안 검사)
함수의 반환 주소, 예외 처리기 주소 또는 특정 유형의 매개 변수를 덮어쓰는 일부 버퍼 오버런을 검색합니다. 버퍼 오버런의 원인은 해커가 버퍼 크기 제한을 적용하지 않는 코드를 악용하는 데 사용하는 기술입니다.
구문
/GS[-]
설명
/GS 는 기본적으로 설정됩니다. 애플리케이션에 보안 노출이 없으면 /GS-를 사용합니다. 버퍼 오버런 검색을 표시하지 않는 방법에 대한 자세한 내용은 safebuffers를 참조 하세요.
보안 검사
컴파일러가 버퍼 오버런 문제의 대상으로 인식하는 함수에서 컴파일러는 반환 주소 앞에 스택에 공간을 할당합니다. 함수 항목에서 할당된 공간은 모듈 로드 시 한 번 계산되는 보안 쿠키와 함께 로드됩니다. 함수 종료 시 및 64비트 운영 체제에서 프레임 해제 중에는 쿠키의 값이 여전히 동일한지 확인하기 위해 도우미 함수가 호출됩니다. 다른 값은 스택의 덮어쓰기가 발생했을 수 있음을 나타냅니다. 다른 값이 검색되면 프로세스가 종료됩니다.
GS 버퍼
버퍼 오버런 보안 검사는 GS 버퍼에서 수행됩니다. GS 버퍼는 다음 중 하나일 수 있습니다.
4바이트보다 크고 요소가 두 개 이상 있고 포인터 형식이 아닌 요소 형식이 있는 배열입니다.
크기가 8바이트보다 크고 포인터가 없는 데이터 구조입니다.
_alloca 함수를 사용하여 할당된 버퍼입니다.
GS 버퍼를 포함하는 모든 클래스 또는 구조체입니다.
예를 들어 다음 문은 GS 버퍼를 선언합니다.
char buffer[20];
int buffer[20];
struct { int a; int b; int c; int d; } myStruct;
struct { int a; char buf[20]; };
그러나 다음 문은 GS 버퍼를 선언하지 않습니다. 처음 두 선언에는 포인터 형식의 요소가 포함됩니다. 세 번째 및 네 번째 문은 크기가 너무 작은 배열을 선언합니다. 다섯 번째 문은 x86 플랫폼의 크기가 8바이트 이하인 구조를 선언합니다.
char *pBuf[20];
void *pv[20];
char buf[4];
int buf[2];
struct { int a; int b; };
보안 쿠키 초기화
/GS 컴파일러 옵션을 사용하려면 쿠키를 사용하는 함수를 실행하기 전에 보안 쿠키를 초기화해야 합니다. EXE 또는 DLL을 입력할 때 보안 쿠키를 즉시 초기화해야 합니다. 기본 VCRuntime 진입점인 mainCRTStartup, wmainCRTStartup, WinMainCRTStartup, wWinMainCRTStartup 또는 _DllMainCRTStartup 사용하는 경우 자동으로 수행됩니다. 대체 진입점을 사용하는 경우 __security_init_cookie 호출하여 보안 쿠키를 수동으로 초기화해야 합니다.
보호되는 항목
/GS 컴파일러 옵션은 다음 항목을 보호합니다.
함수 호출의 반환 주소입니다.
함수에 대한 예외 처리기의 주소입니다.
취약한 함수 매개 변수입니다.
모든 플랫폼에서 /GS 는 반환 주소로 버퍼 오버런을 검색하려고 시도합니다. 버퍼 오버런은 x86 및 x64와 같은 플랫폼에서 더 쉽게 악용되며, 스택에 함수 호출의 반환 주소를 저장하는 호출 규칙을 사용합니다.
x86에서 함수가 예외 처리기를 사용하는 경우 컴파일러는 보안 쿠키를 삽입하여 예외 처리기의 주소를 보호합니다. 프레임 해제 중에 쿠키를 확인합니다.
/GS 는 함수에 전달되는 취약한 매개 변수 를 보호합니다. 취약한 매개 변수는 포인터, C++ 참조, 포인터를 포함하는 C 구조(C++ POD 형식) 또는 GS 버퍼입니다.
취약한 매개 변수는 쿠키 및 지역 변수 앞에 할당됩니다. 버퍼 오버런은 이러한 매개 변수를 덮어쓸 수 있습니다. 또한 이러한 매개 변수를 사용하는 함수의 코드는 함수가 반환되고 보안 검사가 수행되기 전에 공격을 일으킬 수 있습니다. 이러한 위험을 최소화하기 위해 컴파일러는 함수 프롤로그 중에 취약한 매개 변수의 복사본을 만들어 버퍼의 스토리지 영역 아래에 배치합니다.
컴파일러는 다음과 같은 상황에서 취약한 매개 변수의 복사본을 만들지 않습니다.
GS 버퍼를 포함하지 않는 함수입니다.
최적화(/O 옵션)를 사용할 수 없습니다.
변수 인수 목록(...)이 있는 함수입니다.
naked로 표시된 함수입니다.
첫 번째 문에 인라인 어셈블리 코드를 포함하는 함수입니다.
매개 변수는 버퍼 오버런이 발생할 경우 악용될 가능성이 낮은 방식으로만 사용됩니다.
보호되지 않는 항목
/GS 컴파일러 옵션은 모든 버퍼 오버런 보안 공격으로부터 보호하지 않습니다. 예를 들어 개체에 버퍼와 vtable이 있는 경우 버퍼 오버런이 vtable을 손상시킬 수 있습니다.
/GS를 사용하는 경우에도 항상 버퍼 오버런이 없는 보안 코드를 작성합니다.
Visual Studio에서 이 컴파일러 옵션을 설정하려면
프로젝트의 속성 페이지 대화 상자를 엽니다. 자세한 내용은 Visual Studio에서 C++ 컴파일러 및 빌드 속성 설정을 참조하세요.
구성 속성>C/C++>코드 생성 속성 페이지를 선택합니다.
Buffer Security Check 속성을 수정합니다.
프로그래밍 방식으로 이 컴파일러 옵션을 설정하려면
- BufferSecurityCheck을(를) 참조하세요.
예시
이 샘플은 버퍼를 오버런합니다. 이로 인해 런타임에 애플리케이션이 실패합니다.
// 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);
}