보안 고려 사항: Windows 사용자 인터페이스

이 항목에서는 Windows 사용자 인터페이스의 보안 고려 사항에 대한 정보를 제공합니다. 이 항목에서는 보안 문제에 대해 알아야 할 사항을 모두 제공하지 않습니다. 대신 이 기술 영역에 대한 시작점 및 참조로 사용합니다.

컴퓨터 상호 연결이 증가함에 따라 개발자는 이제 애플리케이션 보안에 관심을 가져야 합니다. 그러나 보안은 일반적인 애플리케이션 안전성 및 견고성도 향상시킵니다. 따라서 개발자가 좋은 사용자 환경을 제공할 수 있는 또 다른 방법입니다. 다음 항목에서는 Windows 사용자 인터페이스를 사용할 때 발생할 수 있는 몇 가지 보안 문제에 대해 설명합니다.

문자열 고려 사항

많은 함수, 메시지 및 매크로는 해당 매개 변수에 문자열을 사용합니다. 그러나 문자열은 null 종료 또는 길이에 대해 검사 않는 경우가 많습니다. 관련된 문제는 문자열 또는 버퍼의 길이를 잘못 계산하는 것입니다. 두 경우 모두 버퍼 오버플로 또는 데이터 잘림으로 이어져 애플리케이션에 부정적인 영향을 줄 수 있습니다. 버퍼 오버런 및 기타 보안 문제에 대한 자세한 내용은 마이클 하워드와 데이비드 르블랑, Microsoft Press, 2002의 보안 코드 작성을 참조하세요.

안전한 방식으로 문자열을 처리하려면 다음을 수행해야 합니다.

  • 문자열에서 null 종료 또는 적절한 길이를 적절하게 확인합니다.
  • 특히 TCHAR 값이 포함된 경우 문자열 또는 버퍼의 길이를 확인하려면 특별히 주의해야 합니다.
  • 문자열을 만들거나 이전에 사용한 문자열을 사용하는 경우 0으로 초기화하거나 적절하게 null 종결자를 삽입합니다.

또한 문자열을 처리할 때 Str금고 함수를 사용하는 것이 좋습니다. 이러한 함수는 문자열을 안전하게 처리하도록 설계되었습니다.

사용자 입력

Windows 사용자 인터페이스는 사용자의 정보를 가져오고 응답하는 것과 관련이 있습니다. 그러나 잘못된 데이터를 입력하는 사용자는 원하는지 여부에 관계없이 애플리케이션을 방해할 수 있습니다. 따라서 카드 규칙은 모든 입력의 유효성을 검사해야 한다는 것입니다.

주요 관심사는 문자열 데이터이며 문자열 고려 사항에서 설명합니다. 그러나 모든 유형의 입력은 애플리케이션에서 사용되기 전에 유효성을 검사해야 합니다. 또 다른 관심사는 데이터가 한 지점에서 유효성을 검사하지만 사용되기 전에 변경되는 경우입니다(예: 텍스트 길이를 제공하는 메시지를 수신할 때). 따라서 데이터가 변경될 가능성이 있는 경우 데이터를 사용하기 직전에 데이터를 검사 합니다.

보안 경고

다음 표에는 잘못 사용되는 경우 애플리케이션의 보안을 손상시킬 수 있는 기능이 나열되어 있습니다.

기능 완화 방법
GetAtomName 버퍼의 크기를 지정할 때는 주의해야 합니다.
GlobalGetAtomName 전역 문자열 원자는 모든 애플리케이션에서 액세스할 수 있습니다. 그러나 다른 애플리케이션이 부주의한 경우 참조 수를 잘못 처리하고 삭제할 수 있습니다. 대신 전역 정수 원자를 사용하는 것이 좋습니다.
ImpersonateDdeClientWindow 함수가 실패하면 호출 프로세스의 보안 컨텍스트에서 후속 클라이언트 요청이 수행됩니다. 호출 프로세스가 높은 권한의 계정으로 실행되는 경우 문제가 될 수 있습니다. 따라서 호출이 실패하거나 오류가 발생하는 경우 클라이언트 요청의 실행을 계속하지 않습니다.
DdeImpersonateClient 함수가 실패하면 호출 프로세스의 보안 컨텍스트에서 후속 클라이언트 요청이 수행됩니다. 호출 프로세스가 높은 권한의 계정으로 실행되는 경우 문제가 될 수 있습니다. 따라서 호출이 실패하거나 오류가 발생하는 경우 클라이언트 요청의 실행을 계속하지 않습니다.
GetClipboardFormatName 특히 애플리케이션이 ANSI 및 유니코드 버전 모두에서 사용되는 경우 lpszFormatName 버퍼의 적절한 크기를 잘못 계산하면 버퍼 오버플로가 발생할 수 있습니다. 또한 cchMaxCount 매개 변수보다 긴 경우 문자열이 잘려 정보 손실이 발생할 수 있습니다.
GetMenuString lpString 매개 변수는 TCHAR 버퍼이고 nMaxCount는 TCHAR의 메뉴 문자열 길이입니다. 이러한 매개 변수의 크기를 잘못 지정할 수 있는 것은 문자로 된 메뉴 문자열의 길이입니다. 이러한 매개 변수의 크기를 잘못 조정하면 문자열이 잘리면 데이터가 손실될 수 있습니다.
GetStringTypeA, GetStringTypeEx, GetStringTypeW 버퍼 오버플로를 방지하려면 lpCharType 버퍼의 크기를 올바르게 설정합니다.
LoadLibrary LoadLibrary를 잘못 사용하면 잘못된 DLL을 로드하여 애플리케이션의 보안을 손상시킬 수 있습니다.
LoadString 잘못된 사용에는 nBufferMax 매개 변수에서 잘못된 크기를 지정하는 것이 포함됩니다. 예를 들어 sizeof(lpBuffer)는 버퍼의 크기를 바이트 단위로 제공하므로 함수의 유니코드 버전에 대한 버퍼 오버플로가 발생할 수 있습니다. 버퍼 오버플로 상황은 애플리케이션에서 많은 보안 문제의 원인입니다. 이 경우 사용 sizeof(lpBuffer)/sizeof(TCHAR) 은 버퍼의 적절한 크기를 제공합니다.
lstrcat 이 함수는 SEH(구조적 예외 처리)를 사용하여 액세스 위반 및 기타 오류를 catch합니다. 이 함수는 SEH 오류를 catch할 때 문자열을 null로 종료하지 않고 NULL 없이 NULL을 반환 하며, null을 종료하지 않고 호출자에게 오류를 알리지 않고 반환합니다. 호출자는 공간 부족이 오류 조건이라고 가정해도 안전하지 않습니다. 첫 번째 인수인 lpString1은 lpString2를 보유할 만큼 충분히 커야 하며 닫는 '\0'이면 버퍼 오버런이 발생할 수 있습니다. 버퍼 오버런은 액세스 위반이 발생하는 경우 애플리케이션에 대한 서비스 거부 공격으로 이어질 수 있습니다. 최악의 경우 버퍼 오버런은 특히 lpString1이 스택 기반 버퍼인 경우 공격자가 실행 코드를 프로세스에 삽입하도록 허용할 수 있습니다. 다음 대안 중 하나를 사용하는 것이 좋습니다. StringCbCat 또는 StringCchCat.
lstrcpy 이 함수는 SEH(구조적 예외 처리)를 사용하여 액세스 위반 및 기타 오류를 catch합니다. 이 함수는 SEH 오류를 catch할 때 문자열을 null로 종료하지 않고 NULL 없이 NULL을 반환 하며, null을 종료하지 않고 호출자에게 오류를 알리지 않고 반환합니다. 호출자는 공간 부족이 오류 조건이라고 가정해도 안전하지 않습니다. 첫 번째 인수인 lpString1은 lpString2를 보유할 만큼 충분히 커야 하며 닫는 '\0'이면 버퍼 오버런이 발생할 수 있습니다. 버퍼 오버런은 액세스 위반이 발생하는 경우 애플리케이션에 대한 서비스 거부 공격으로 이어질 수 있습니다. 최악의 경우 버퍼 오버런은 특히 lpString1이 스택 기반 버퍼인 경우 공격자가 실행 코드를 프로세스에 삽입하도록 허용할 수 있습니다. 대신 StringCchCopy를 사용하는 것이 좋습니다.
lstrcpyn 이 함수는 SEH(구조적 예외 처리)를 사용하여 액세스 위반 및 기타 오류를 catch합니다. 이 함수는 SEH 오류를 catch할 때 문자열을 null로 종료하지 않고 NULL 없이 NULL을 반환 하며, null을 종료하지 않고 호출자에게 오류를 알리지 않고 반환합니다. 호출자는 공간 부족이 오류 조건이라고 가정해도 안전하지 않습니다. lpString1이 복사된 문자열을 포함할 만큼 충분히 크지 않으면 버퍼 오버런이 발생할 수 있습니다. 또한 전체 문자열을 복사할 때 sizeof는 WCHAR아닌 바이트 수를 반환합니다. 이 sizeof는 문자가 아닌 바이트 수를 반환하며 이 함수의 유니코드 버전에서는 올바르지 않습니다. 버퍼 오버런은 액세스 위반이 발생하는 경우 애플리케이션에 대한 서비스 거부 공격을 일으킬 수 있습니다. 최악의 경우 버퍼 오버런은 특히 lpString1이 스택 기반 버퍼인 경우 공격자가 실행 코드를 프로세스에 삽입하도록 허용할 수 있습니다. 대신 StringCchCopy를 사용하는 것이 좋습니다.
lstrlen lstrlen은 lpStringnull로 끝나는 문자열이라고 가정합니다. 그렇지 않은 경우 버퍼 오버런 또는 애플리케이션에 대한 서비스 거부 공격으로 이어질 수 있습니다. 다음 대안 중 하나를 사용하는 것이 좋습니다. StringCbLength 또는 StringCchLength.
wsprintf lpOut에서 반환된 문자열은 null로 종료되지 않습니다. 또한 %s 형식을 사용하지 않도록 하여 버퍼 오버런이 발생할 수 있습니다. 액세스 위반이 발생하면 애플리케이션에 대한 서비스 거부가 발생합니다. 더 나쁜 경우 공격자는 실행 코드를 삽입할 수 있습니다. 다음 대안 중 하나를 사용하는 것이 좋습니다. StringCbPrintf, StringCbPrintfEx, StringCbVPrintf, StringCbVPrintfEx, StringCchPrintf, StringCchPrintfEx, StringCchVPrintf 또는 StringCchVPrintfEx.
wvsprintf lpOutput에서 반환된 문자열은 null로 종료되지 않습니다. 또한 %s 형식을 사용하지 않도록 하여 버퍼 오버런이 발생할 수 있습니다. 이로 인해 액세스 위반이 발생하거나 공격자가 실행 코드를 삽입할 수 있는 경우 서비스 거부가 발생할 수 있습니다. 다음 대안 중 하나를 사용하는 것이 좋습니다. StringCbPrintf, StringCbPrintfEx, StringCbVPrintf, StringCbVPrintfEx, StringCchPrintf, StringCchPrintfEx, StringCchVPrintf 또는 StringCchVPrintfEx.

 

Microsoft 보안

보안 및 ID

보안 방법 인덱스

Microsoft 보안 대응 센터

보안 API에 대한 모범 사례