/GS(버퍼 보안 검사)

업데이트: 2007년 11월

반환 주소를 덮어쓰는 버퍼 오버런을 탐지합니다. 버퍼 오버런은 버퍼 크기 제한을 적용하지 않는 코드를 공격할 때 일반적으로 사용되는 기법입니다. 이러한 방법은 보안 검사를 컴파일된 코드에 추가하면 가능합니다.

/GS[-]

설명

/GS는 기본적으로 사용됩니다. 응용 프로그램이 보안 위험에 노출되지 않도록 하려면 /GS를 사용하는 것이 좋습니다.

/GS에 대한 자세한 내용은 Compiler Security Checks In Depth를 참조하십시오.

컴파일러는 로컬 문자열 버퍼가 있는 함수 또는 x86에서 예외 처리를 사용하는 함수에 검사를 추가합니다. 문자열 버퍼는 요소 크기가 1바이트 또는 2바이트이고 전체 배열의 크기가 적어도 5바이트인 배열 또는 _alloca를 사용하여 할당된 버퍼로 정의됩니다.

모든 플랫폼에서 함수에 로컬 문자열 버퍼가 있는 경우 컴파일러는 쿠키를 추가하여 함수의 반환 주소를 보호합니다. 이 쿠키는 함수가 종료될 때 및 64비트 운영 체제 또는 x86에서 어떤 형태로든 예외 처리를 사용하는 함수의 프레임을 해제하는 동안 검사됩니다. x86에서 컴파일러는 함수의 예외 처리기 주소를 보호하는 쿠키도 추가합니다. 이 쿠키는 프레임을 해제하는 동안 검사됩니다.

/GS는 주로 반환 주소에 대한 직접 버퍼 오버런을 탐지합니다. 함수 호출의 반환 주소를 스택에 저장하는 호출 규칙을 사용하는 컴퓨터는 버퍼 오버런 공격에 더 취약합니다. 예를 들어, x86은 함수 호출의 반환 주소를 스택에 저장하는 호출 규칙을 사용합니다.

컴파일러가 버퍼 오버런 문제가 발생할 수 있다고 간주하는 함수에 대해서는 스택에서 반환 주소 앞에 공간을 할당합니다. 함수가 시작될 때, 모듈 로드 시 한 번 계산되는 보안 쿠키와 함께 할당된 공간이 로드됩니다. 그런 다음 함수가 종료될 때 도우미 함수가 호출되어 쿠키 값이 동일한지 확인합니다.

값이 동일하지 않으면 스택을 덮어썼을 가능성이 있으므로 프로세스가 종료됩니다. Visual C++ 2005 이전 버전에서는 스택 덮어쓰기를 보고하는 대화 상자가 열렸습니다.

/GS는 공격에 취약한 매개 변수가 함수에 전달되는 경우 이를 보호하는 역할도 합니다. 공격에 취약한 매개 변수로는 포인터, 문자열 버퍼, C++ 참조 등이 포함된 C 구조체(C++ POD 형식), C++ 참조 또는 포인터가 있습니다.

이러한 매개 변수는 쿠키 및 지역 변수 앞에 할당됩니다. 버퍼 오버런에서는 이러한 매개 변수를 덮어쓸 수 있습니다. 이와 같은 매개 변수를 사용하는 함수의 코드는 함수에서 제어가 반환되기 전에 공격을 받을 수 있으므로 보안 검사를 빠져나가게 됩니다. 이러한 위험을 최소화하기 위해 컴파일러는 함수 프롤로그 도중 공격에 취약한 매개 변수의 복사본을 만들고 이러한 복사본을 버퍼의 저장 영역 아래에 추가합니다.

다음과 같은 상황에서는 컴파일러가 공격에 취약한 매개 변수에 대한 보안 기능을 제공하지 않습니다.

  • 함수에 버퍼가 포함되어 있지 않은 경우

  • 최적화(/O 옵션(코드 최적화))를 사용하지 않는 경우

  • 함수에 가변 인수 목록(...)을 사용하는 경우

  • 함수가 naked (C++)로 표시된 경우

  • 함수의 첫 번째 문에 인라인 어셈블리 코드가 포함된 경우

  • 버퍼 오버런이 발생해도 공격에 사용될 가능성이 적은 방식으로만 매개 변수가 사용되는 경우

/GS을 사용하면 보안 쿠키를 초기화해야 합니다. 쿠키를 사용하는 모든 함수가 실행되기 전에 이 쿠키를 초기화해야 합니다. 보안 쿠키는 EXE 또는 DLL에 진입할 때 초기화되어야 합니다. 이 초기화는 기본 CRT 진입점(mainCRTStartup, wmainCRTStartup, WinMainCRTStartup, wWinMainCRTStartup 또는 _DllMainCRTStartup)을 사용할 때 자동으로 수행되지만, 대체 진입점을 사용하는 경우에는 __security_init_cookie를 호출하여 수동으로 초기화해야 합니다.

/GS/clr(공용 언어 런타임 컴파일)를 사용하여 컴파일할 때 관리되는 함수에 대해 지원됩니다.

/GS는 모든 버퍼 오버런 보안 공격에 대해 응용 프로그램을 보호하지는 않습니다. 예를 들어, 개체에 버퍼와 vtable이 있는 경우 버퍼 오버런으로 인해 vtable이 손상되어 보안 공격이 발생할 수 있습니다.

/GS를 사용하는 경우에도 안전한 코드를 작성하도록 해야 합니다. 즉, 코드에서 버퍼 오버런이 발생하지 않도록 주의해야 합니다. /GS를 사용하면 코드에 남아 있을지도 모르는 버퍼 오버런으로부터 응용 프로그램을 보호할 수 있습니다.

Visual Studio 개발 환경에서 이 컴파일러 옵션을 설정하려면

  1. 프로젝트의 속성 페이지 대화 상자를 엽니다. 자세한 내용은 방법: 프로젝트 속성 페이지 열기를 참조하십시오.

  2. C/C++ 폴더를 클릭합니다.

  3. 코드 생성 속성 페이지를 클릭합니다.

  4. 버퍼 보안 검사 속성을 수정합니다.

프로그래밍 방식으로 이 컴파일러 옵션을 설정하려면

예제

이 샘플에서는 버퍼 오버런이 발생하여 런타임에 응용 프로그램이 올바르게 실행되지 않습니다.

// 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);
}

참고 항목

참조

컴파일러 옵션

컴파일러 옵션 설정