드라이버 보안 검사 목록
이 문서에서는 드라이버 개발자를 위한 드라이버 보안 검사 목록을 제공하여 드라이버가 손상될 위험을 줄입니다. 드라이버 보안은 중요하며 안정성에 직접적인 영향을 줍니다. Windows에서 잘못된 메모리 액세스가 발생하는 것을 감지하면 OS가 종료되고 파란색 오류 화면이 표시됩니다. Windows 파트너는 실패한 드라이버가 고객의 삶에 미치는 중대한 영향을 줄이기 위해 노력해야 합니다.
안전하고 신뢰할 수 있는 드라이버를 제공하는 이점에 대한 자세한 내용은 드라이버 보안 지침참조하세요.
드라이버 보안 개요
보안 결함은 공격자가 무단 액세스를 얻거나, 시스템을 조작하거나, 데이터를 손상시켜 시스템이 충돌하거나 사용할 수 없게 하는 방식으로 드라이버가 오작동할 수 있도록 하는 결함입니다. 또한 드라이버 코드의 취약성을 통해 공격자가 커널에 액세스하여 전체 OS를 손상할 수 있습니다.
대부분의 개발자가 드라이버에서 작업할 때는 악의적인 공격자가 코드 내에서 취약성을 악용하려고 하는지 여부가 아니라 드라이버가 제대로 작동하도록 하는 데 중점을 두고 있습니다. 그러나 드라이버가 릴리스된 후 공격자는 보안 결함을 조사하고 식별하려고 시도할 수 있습니다. 개발자는 이러한 취약성의 가능성을 최소화하기 위해 디자인 및 구현 단계에서 이러한 문제를 고려해야 합니다. 목표는 드라이버가 릴리스되기 전에 알려진 모든 보안 결함을 제거하는 것입니다.
더 안전한 드라이버를 만들려면 시스템 설계자(드라이버에 대한 잠재적 위협을 의식적으로 생각), 코드를 구현하는 개발자(악용의 근원이 될 수 있는 일반적인 작업을 방어적으로 코딩) 및 테스트 팀(약점과 취약성을 사전에 찾으려고 시도)의 협력이 필요합니다. 이러한 모든 활동을 적절히 조정하면 드라이버의 보안이 크게 향상됩니다.
드라이버와 관련된 문제를 방지하는 것 외에도 커널 메모리를 보다 정확하게 사용하는 등 설명된 많은 단계를 수행하면 드라이버의 안정성이 향상됩니다. 이렇게 하면 지원 비용이 감소하고 제품에 대한 고객 만족도가 높아질 수 있습니다. 아래 검사 목록의 작업을 완료하면 이러한 모든 목표를 달성하는 데 도움이 됩니다.
보안 검사 목록:이러한 각 항목에 설명된 보안 작업을 완료합니다.
드라이버 프레임워크 사용
드라이버 보안 코딩 지침 따르기
HVCI 호환 코드 구현
기술별 코드 모범 사례 따르기
ko-KR: 드라이버 코드에 SAL 주석을 추가하세요
하드웨어 호환성 프로그램 테스트 코드를 확인합니다.
BinSkim 및 SignTool 같은 도구를 사용하여 드라이버를 배송할 준비가 되어 있는지 확인합니다.
Windows 업데이트 사용하여 적절한 릴리스 드라이버 서명 실행 및 드라이버 패키지 배포
Microsoft 취약 및 악성 드라이버 보고 센터 사용하여 드라이버를 보고하는 방법을 이해합니다.
주요 내용 요약 검토
커널 드라이버가 필요한지 확인
보안 검사 목록 항목 #1:커널 드라이버가 필요하고 Windows 서비스 또는 앱과 같은 낮은 위험 접근 방식이 더 나은 옵션이 아닌지 확인합니다.
커널 드라이버는 Windows 커널에 있으며 커널에서 실행할 때 문제가 발생하면 전체 운영 체제가 노출됩니다. 다른 옵션을 사용할 수 있는 경우 새 커널 드라이버를 만드는 것보다 비용이 낮고 관련 위험이 적을 수 있습니다.
더 많은 정보가 필요한 경우 내장된 Windows 드라이버 사용에 대해 자세히 알아보려면 드라이버를 작성할 필요가 있습니까?를 참조하십시오.
백그라운드 작업에 대한 정보를 얻으려면 백그라운드 작업으로 앱을 지원하세요를 참조하세요.
Windows 서비스 사용에 대한 자세한 내용은 Services참조하세요.
드라이버 프레임워크 사용
보안 검사 목록 항목 #2:드라이버 프레임워크를 사용하여 코드 크기를 줄이고 안정성과 보안을 강화합니다.
Windows 드라이버 프레임워크 사용하여 코드 크기를 줄이고 안정성과 보안을 강화합니다. 시작하려면 WDF를 사용하여 드라이버 개발하기를 검토하십시오. 위험 수준이 낮은 UMDF(사용자 모드 드라이버 프레임워크) 사용에 대한 자세한 내용은 드라이버 모델 선택참조하세요.
WDM(Windows 드라이버 모델)
WDF(Windows 드라이버 프레임워크) 소스 코드는 오픈 소스이며 GitHub에서 사용할 수 있습니다. Windows에서 제공하는 것과 동일한 WDF 소스 코드입니다. 드라이버와 WDF 간의 상호 작용을 따를 수 있는 경우 드라이버를 보다 효과적으로 디버그할 수 있습니다. https://github.com/Microsoft/Windows-Driver-Frameworks에서 그것을 다운로드하세요.
DMF - 드라이버 모듈 프레임워크
드라이버 프로젝트에서 DMF(드라이버 모듈 프레임워크)를 사용하는 것이 좋습니다. Microsoft Surface 팀에서 개발한 DMF는 DMF 모듈이라는 WDF 개체를 만들 수 있는 프레임워크입니다. 이러한 DMF 모듈에 대한 코드는 서로 다른 드라이버 간에 공유할 수 있습니다. 또한 DMF는 드라이버용으로 개발된 DMF 모듈 라이브러리를 제공하고 스레드 및 I/O 관리와 같은 작업에 코드 재사용을 제공합니다. DMF 모듈은 드라이버 작업을 더 작은 단위로 캡슐화하는 데 사용됩니다. 각 모듈은 자체 포함되며 자체 코드, 컨텍스트 및 콜백을 포함하므로 더 쉽게 다시 사용할 수 있습니다. 자세한 내용은 드라이버 모듈 프레임워크 소개 및 GitHub 사이트 설명서참조하세요.
드라이버의 접근 제어 관리
보안 검사 목록 항목 #3:드라이버를 검토하여 액세스를 제대로 제어하고 있는지 확인합니다.
드라이버 액세스 제어 관리 - WDF
드라이버는 사용자가 컴퓨터의 장치 및 파일에 부적절하게 액세스하지 못하도록 하기 위해 노력해야 합니다. 디바이스 및 파일에 대한 무단 액세스를 방지하려면 다음을 수행해야 합니다.
필요한 경우에만 디바이스 개체의 이름을 지정합니다. 명명된 디바이스 개체는 일반적으로 레거시 이유(예: 특정 이름을 사용하여 디바이스를 열 것으로 예상되는 애플리케이션이 있거나 PNP가 아닌 디바이스/제어 디바이스를 사용하는 경우)에만 필요합니다. WDF 드라이버는 WdfDeviceCreateSymbolicLink사용하여 기호 링크를 만들기 위해 PnP 디바이스 FDO의 이름을 지정할 필요가 없습니다.
디바이스 개체 및 인터페이스에 대한 액세스를 보호합니다.
애플리케이션 또는 다른 WDF 드라이버가 PnP 디바이스 PDO에 액세스할 수 있도록 하려면 디바이스 인터페이스를 사용해야 합니다. 자세한 내용은 장치 인터페이스 사용을 참조하세요. 디바이스 인터페이스는 디바이스 스택의 PDO에 대한 기호 링크 역할을 합니다.
PDO에 대한 액세스를 제어하는 더 좋은 방법 중 하나는 INF에서 SDDL 문자열을 지정하는 것입니다. SDDL 문자열이 INF 파일에 없는 경우 Windows는 기본 보안 설명자를 적용합니다. 자세한 내용은 디바이스 개체 보안 및 디바이스 개체의 SDDL를 참조하세요.
액세스 제어에 대한 자세한 내용은 다음을 참조하세요.
이름, 보안 설명자 및 디바이스 클래스 - 액세스할 수 있는 디바이스 개체 만들기... 및 안전 2017년 1월과 2월 OSR발행한 NT 인사이더 뉴스레터.
드라이버의 액세스 제어 관리 - WDM
WDM 드라이버로 작업 중이고 명명된 디바이스 개체를 사용한 경우 IoCreateDeviceSecure 사용하고 SDDL을 지정하여 보호할 수 있습니다. IoCreateDeviceSecure를 구현할 때, 항상 DeviceClassGuid에 사용자 지정 클래스 GUID를 지정하세요. 여기서 기존 클래스 GUID를 지정해서는 안 됩니다. 이렇게 하면 해당 클래스에 속한 다른 디바이스에 대한 보안 설정 또는 호환성이 손상될 수 있습니다. 자세한 내용은 WdmlibIoCreateDeviceSecure참조하세요.
자세한 내용은 다음을 참조하세요.
드라이버 개발자를 위한 windows 보안 모델
SID(보안 식별자) 위험 계층 구조
다음 섹션에서는 드라이버 코드에 사용되는 일반적인 SID의 위험 계층 구조를 설명합니다. SDDL에 대한 일반 정보를 확인하려면 SDDL for Device Objects, SID 문자열및 SDDL 문자열 구문를 참조하세요.
낮은 권한 호출자가 커널에 액세스할 수 있는 경우 코드 위험이 증가한다는 것을 이해하는 것이 중요합니다. 이 요약 다이어그램에서는 드라이버 기능에 대한 낮은 권한 SID 액세스를 허용하면 위험이 증가합니다.
SY (System)
\/
BA (Built-in Administrators)
\/
LS (Local Service)
\/
BU (Built-in User)
\/
AC (Application Container)
일반 최소 권한 보안 원칙에 따라 드라이버가 작동하는 데 필요한 최소 액세스 수준만 구성합니다.
WDM 세분화된 IOCTL 보안 제어
Windows의 IOCTL(입력/출력 제어)은 디바이스별 입력/출력 작업에 대한 시스템 호출입니다. IOCTL은 애플리케이션에서 디바이스 드라이버와 통신하는 데 사용되므로 하드웨어에서 명령을 보내거나 정보를 요청할 수 있습니다. 자세한 내용은 I/O 제어 코드 소개 및 예제 I/O 요청 - 개요참조하세요.
사용자 모드 호출자가 IOCTL을 보낼 때 보안을 더욱 관리하기 위해 드라이버 코드에는 IoValidateDeviceIoControlAccess 함수가 포함될 수 있습니다. 이 함수를 사용하면 드라이버가 액세스 권한을 확인할 수 있습니다. IOCTL을 받으면 드라이버는 IoValidateDeviceIoControlAccess호출하여 FILE_READ_ACCESS, FILE_WRITE_ACCESS 또는 둘 다를 지정할 수 있습니다.
세분화된 IOCTL 보안 제어를 구현해도 위에서 설명한 기술을 사용하여 드라이버 액세스를 관리할 필요가 없습니다.
자세한 내용은 I/O 제어 코드
소프트웨어 전용 드라이버에 대한 액세스 제어
보안 검사 목록 항목 #4:소프트웨어 전용 드라이버를 만들려면 추가 액세스 제어를 구현해야 합니다.
소프트웨어 전용 커널 드라이버는 PnP(플러그 앤 플레이)를 사용하여 특정 하드웨어 ID와 연결되지 않으며 모든 PC에서 실행할 수 있습니다. 이러한 드라이버는 원래 의도된 용도가 아닌 다른 목적으로 사용되어 공격 벡터를 만들 수 있습니다.
소프트웨어 전용 커널 드라이버에는 추가 위험이 있으므로 특정 하드웨어에서 실행되도록 제한해야 합니다. 예를 들어 고유한 PnP ID를 사용하여 PnP 드라이버를 만들거나 SMBIOS 테이블에서 특정 하드웨어가 있는지 확인합니다.
예를 들어 OEM Fabrikam이 시스템에 대해 오버클럭 유틸리티를 사용하도록 설정하는 드라이버를 배포하려고 하는 경우를 상상해 보십시오. 이 소프트웨어 전용 드라이버가 다른 OEM의 시스템에서 실행되는 경우 시스템 불안정 또는 손상이 발생할 수 있습니다. Fabrikam의 시스템에는 Windows 업데이트를 통해 업데이트할 수 있는 PnP 드라이버를 만들 수 있도록 고유한 PnP ID가 포함되어야 합니다. 이것이 불가능하고 Fabrikam이 레거시 드라이버를 작성할 경우 해당 드라이버는 기능을 사용하도록 설정하기 전에 SMBIOS 테이블을 검사하여 Fabrikam 시스템에서 실행되는지 확인하는 다른 방법을 찾아야 합니다.
드라이버 보안 코딩 지침 준수
보안 검사 목록 항목 #5:코드를 검토하고 알려진 코드 취약성을 제거합니다.
보안 드라이버를 만드는 핵심 활동은 알려진 소프트웨어 취약성을 방지하기 위해 변경해야 하는 코드의 영역을 식별하는 것입니다. 이러한 알려진 소프트웨어 취약성 중 상당수는 다른 사용자가 덮어쓰거나 드라이버에서 사용하는 메모리 위치를 손상시키는 문제를 방지하기 위해 메모리 사용을 엄격하게 추적하는 작업을 처리합니다.
CodeQL 및 드라이버별 테스트와 같은 코드 검색 도구를 사용하여 이러한 취약성 중 일부(전부는 아님)를 찾을 수 있습니다. 이러한 도구 및 테스트는 이 항목의 뒷부분에 설명되어 있습니다.
메모리 버퍼
항상 입력 및 출력 버퍼의 크기를 확인하여 버퍼가 요청된 모든 데이터를 저장할 수 있는지 확인합니다. 자세한 내용은 버퍼 크기 확인 실패를 참조하십시오.
호출자에게 반환하기 전에 모든 출력 버퍼를 0으로 올바르게 초기화합니다. 자세한 내용은 출력 버퍼 초기화 실패를 참조하세요.
가변 길이 버퍼의 유효성을 검사합니다. 자세한 내용은 Variable-Length 버퍼유효성 검사 실패를 참조하세요. 버퍼를 사용하고 ProbeForRead 사용하여 버퍼 주소의 유효성을 검사하는 방법에 대한 자세한 내용은 버퍼 처리참조하세요.
IOCTL을 사용하여 데이터 버퍼에 액세스하는 데 적절한 방법 사용
Windows 드라이버의 주요 책임 중 하나는 사용자 모드 애플리케이션과 시스템 디바이스 간에 데이터를 전송하는 것입니다. 데이터 버퍼에 액세스하는 세 가지 방법은 다음 표에 나와 있습니다.
IOCTL 버퍼 형식 | 요약 | 자세한 내용을 확인하려면 |
---|---|---|
METHOD_BUFFERED | 대부분의 상황에 권장 | 버퍼링된 I/O 사용하기 |
METHOD_IN_DIRECT 또는 METHOD_OUT_DIRECT | 일부 고속 하드웨어 I/O에 사용됨 | 직접 I/O 사용하기 |
메서드_네이더 | 가능하면 피하세요. | 버퍼링도 직접 I/O도 사용하지 않기 |
일반적으로 버퍼링된 I/O는 가장 안전한 버퍼링 메서드를 제공하므로 권장됩니다. 그러나 버퍼링된 I/O를 사용하는 경우에도 완화해야 하는 포함된 포인터와 같은 위험이 있습니다.
IOCTL에서 버퍼를 사용하는 방법에 대한 자세한 내용은 데이터 버퍼액세스하기 위한
IOCTL 버퍼링된 I/O 사용 오류
IOCTL 관련 버퍼의 크기를 확인합니다. 자세한 내용은 버퍼 크기 확인 실패를 참조하십시오.
출력 버퍼를 올바르게 초기화합니다. 자세한 내용은 출력 버퍼 초기화 실패를 참조하세요.
가변 길이 버퍼의 유효성을 올바르게 검사합니다. 자세한 내용은 Variable-Length 버퍼유효성 검사 실패를 참조하세요.
버퍼링된 I/O를 사용하는 경우 IO_STATUS_BLOCK 구조체 정보 필드에서 OutputBuffer의 적절한 길이를 확인하고 반환합니다. 읽기 요청에서 직접 길이를 반환하지 마세요. 예를 들어 사용자 공간에서 반환된 데이터가 4K 버퍼가 있음을 나타내는 상황을 고려합니다. 드라이버가 실제로 200바이트만 반환해야 하지만 대신 정보 필드에서 4K를 반환하는 경우 정보 공개 취약성이 발생했습니다. 이 문제는 이전 버전의 Windows에서는 I/O 관리자가 버퍼링된 I/O에 사용하는 버퍼가 0이 아니므로 발생합니다. 따라서 사용자 앱은 원래 200바이트의 데이터와 더불어 버퍼에 있던 4K-200바이트의 데이터(비페이징 풀의 내용)를 가져옵니다. 이 시나리오는 IOCTL뿐만 아니라 버퍼링된 I/O의 모든 용도로 발생할 수 있습니다.
IOCTL의 직접 I/O 오류
길이가 0인 버퍼를 올바르게 처리합니다. 자세한 내용은 직접 I/O
사용자 공간 주소 참조 오류
버퍼링된 I/O 요청에 포함된 포인터의 유효성을 검사합니다. 참고 사항: 오류를 참조하려면 User-Space 주소를 확인하세요.
사용하기 전에 ProbeForRead같은 API를 사용하여 사용자 공간의 주소에 대한 유효성을 검사합니다.
드라이버 코드는 메모리를 올바르게 사용해야 합니다.
모든 드라이버 풀 할당은 NX(실행 불가능한) 풀에 있어야 합니다. NX 메모리 풀을 사용하는 것은 NP(실행 파일 비페이징) 풀을 사용하는 것보다 본질적으로 더 안전하며 오버플로 공격에 대한 더 나은 보호를 제공합니다.
드라이버가 HVCI 가상화를 지원할 수 있도록 추가 메모리 요구 사항이 있습니다. 자세한 내용은 이 문서의 뒷부분에 HVCI 호환 코드 구현
참조하세요.
TOCTOU 취약성
직접 I/O(IOCTL 또는 읽기/쓰기)를 사용하는 경우 TOCTOU(사용 시간) 취약성을 확인할 수 있는
이 위험을 관리하려면 사용자 데이터 버퍼에서 유효성을 검사해야 하는 매개 변수를 스택 또는 풀과 같은 커널 모드에서만 액세스할 수 있는 메모리로 복사합니다. 그런 다음, 사용자 애플리케이션에서 데이터에 액세스할 수 없으면 유효성을 검사한 다음 전달된 데이터에 대해 작동합니다.
MSR 모델별 레지스터 읽기 및 쓰기
__readmsr 및 __writemsr 같은 컴파일러 내장 함수를 사용하여 모델별 레지스터에 액세스할 수 있습니다. 이 액세스가 필요한 경우 드라이버는 항상 읽거나 쓸 레지스터가 예상 인덱스 또는 범위로 제한되는지 확인해야 합니다.
자세한 내용 및 코드 예제는 커널 모드 드라이버높은 권한 있는 동작을 제한하기 위한
처리
- 사용자 모드와 커널 모드 메모리 간에 전달된 핸들의 유효성을 검사합니다. 자세한 내용은 핸들링 관리 및 개체 핸들 유효성 검사 실패를 참조하세요.
디바이스 개체
디바이스 개체를 보호합니다. 자세한 내용은 디바이스 개체 보안
참조하세요. 디바이스 개체의 유효성을 검사합니다. 자세한 내용은 디바이스 개체유효성 검사 실패를 참조하세요.
IRP
Windows I/O 요청 패킷(IRP)은 운영 체제와 커널 모드 드라이버 간에 I/O 요청을 전달하는 데 사용되며 패킷에 필요한 모든 정보를 캡슐화합니다. IRP는 비동기 데이터 전송, 동기화 및 오류 처리를 용이하게 하여 하드웨어 디바이스와의 효율적이고 안정적인 통신을 보장합니다. 자세한 내용은
WDF 및 IRP
WDF를 사용하는 한 가지 이점은 WDF 드라이버가 일반적으로 IRP에 직접 액세스하지 않는다는 것입니다. 예를 들어 프레임워크는 읽기, 쓰기 및 디바이스 I/O 제어 작업을 나타내는 WDM IRP를 KMDF/UMDF가 I/O 큐에서 수신하는 프레임워크 요청 개체로 변환합니다. 가능하면 WDF를 사용하는 것이 좋습니다.
WDM 드라이버를 작성해야 하는 경우 다음 지침을 검토합니다.
IRP I/O 버퍼 제대로 관리
IRP 입력 값의 유효성을 검사하는 방법을 다루는 다음 항목을 검토합니다.
버퍼링된 I/O 사용하여 DispatchReadWrite
버퍼 주소 및 길이와 같이 IRP와 연결된 값의 유효성을 검사합니다.
I/O를 사용하지 않도록 선택한 경우 읽기 및 쓰기와 달리 버퍼링된 I/O 및 Direct I/O와 달리 I/O IOCTL을 사용하지 않을 때는 I/O 관리자가 버퍼 포인터와 길이의 유효성을 검사하지 않는다는 점에 유의하세요.
IRP 완료 작업을 올바르게 처리
드라이버는 실제로 IRP를 지원하고 처리하지 않는 한 상태 값이 STATUS_SUCCESS
인 IRP를 완료해서는 안 됩니다. IRP 완료 작업을 올바르게 처리하는 방법에 대한 정보는 완료 IRPs를 참조하세요.
드라이버 IRP 보류 상태 관리
드라이버는 IRP를 저장하기 전에 보류 중인 IRP를 표시해야 하며, IoMarkIrpPending 호출과 할당을 모두 연동 시퀀스에 포함하는 것이 좋습니다. 자세한 내용은 디바이스가일시 중지될 때
IRP 취소 작업을 올바르게 처리
취소 작업은 일반적으로 비동기적으로 실행되므로 제대로 코딩하기 어려울 수 있습니다. 이 코드는 일반적으로 실행 중인 시스템에서 자주 실행되지 않으므로 취소 작업을 처리하는 코드의 문제는 오랫동안 눈에 띄지 않을 수 있습니다.
IRP 취소제공된 모든 정보를 읽고 이해해야 합니다. IRP 취소 동기화를
취소 작업들과 관련된 동기화 문제를 최소화하는 권장 방법 중 하나는 취소 안전 IRP 큐를 구현하는 것입니다.
IRP 정리 및 종료 작업을 적절하게 처리하십시오.
IRP_MJ_CLEANUP 요청과 IRP_MJ_CLOSE 요청의 차이점을 이해해야 합니다. 정리 요청은 애플리케이션이 파일 개체의 모든 핸들을 닫은 후에 도착하지만 때로는 모든 I/O 요청이 완료되기 전에 도착합니다. 파일 개체에 대한 모든 I/O 요청이 완료되거나 취소된 후 닫기 요청이 도착합니다. 자세한 내용은 다음을 참조하세요.
DispatchCreate, DispatchClose 및 DispatchCreateClose 루틴
IRP를 올바르게 처리하는 방법에 대한 자세한 내용은 IRP처리의 추가 오류를 참조하세요.
안전 함수 사용
안전한 문자열 함수를 사용합니다. 자세한 내용은 안전한 문자열 함수 사용에 대한 정보를 참조하세요.
안전한 산술 함수를 사용합니다. 자세한 내용은 안전한 정수 라이브러리 루틴참조하세요.
안전한 변환 함수를 사용합니다. 자세한 내용은 Kernel-Mode 안전한 정수 함수요약을 참조하세요.
기타 보안 문제
잠금 또는 연동된 시퀀스를 사용하여 경합 상태를 방지합니다. 자세한 내용은 다중 프로세서 환경에서의 오류을 참조하세요.
설치 또는 사용 중에 드라이버 또는 관련 소프트웨어 패키지에 의해 TDI(네트워크 전송 드라이버 인터페이스) 필터 또는 LSP(계층화된 서비스 공급자)가 설치되지 않았는지 확인합니다. 대신 WFP(Windows 필터링 플랫폼) 같은 최신 API를 사용합니다.
추가 코드 취약성
이 문서에서는 여기서 다루는 가능한 취약성 외에도 커널 모드 드라이버 코드의 보안 강화에 대한 추가 정보를 제공합니다. 신뢰할 수 있는 Kernel-Mode 드라이버 만들기.
C 및 C++ 보안 코딩에 대한 자세한 내용은 이 문서의 끝에
HVCI 호환 코드 구현
보안 검사 목록 항목 #6:드라이버가 메모리를 사용하여 HVCI와 호환되는지 유효성을 검사합니다.
메모리 무결성 및 HVCI 호환성
HVCI(하이퍼바이저 보호 코드 무결성)라고도 하는 메모리 무결성은 하드웨어 기술 및 가상화를 사용하여 CI(코드 무결성) 의사 결정 함수를 나머지 운영 체제와 격리합니다. 가상화 기반 보안을 사용하여 CI를 격리하는 경우 커널 메모리가 실행될 수 있는 유일한 방법은 CI 확인을 통해서입니다. 즉, 커널 메모리 페이지는 쓰기 가능 및 실행 파일(W+X)이 될 수 없으며 실행 코드는 직접 수정할 수 없습니다.
HVCI 호환 코드를 구현하려면 드라이버 코드에서 다음을 수행해야 합니다.
- 기본적으로 NX에 옵트인
- 메모리 할당에 NX API/플래그 사용(NonPagedPoolNx)
- 쓰기 가능 및 실행 가능한 섹션을 사용하지 않습니다.
- 실행 가능한 시스템 메모리를 직접 수정하지 않습니다.
- 커널에서 동적 코드를 사용하지 않음
- 데이터 파일을 실행 파일로 로드하지 않음
- 섹션 정렬은 0x1000(PAGE_SIZE)의 배수입니다. 예를 들어 DRIVER_ALIGNMENT=0x1000
도구 및 호환되지 않는 메모리 호출 목록을 사용하는 방법에 대한 자세한 내용은 HVCI 호환 코드구현을 참조하세요.
관련 시스템 기본 사항 보안 테스트에 대한 자세한 내용은 하이퍼바이저 코드 무결성 테스트 및 HVCI(Hypervisor-Protected 코드 무결성)참조하세요.
디바이스 설치 보안 강화
보안 검사 목록 항목 #7:드라이버 inf 만들기 및 설치 지침을 검토하여 모범 사례를 따르고 있는지 확인합니다.
드라이버 패키지를 설치하는 코드를 만들 때 디바이스 설치가 항상 안전한 방식으로 수행되는지 확인해야 합니다. 보안 디바이스 설치는 다음을 수행합니다.
- 디바이스 및 해당 디바이스 인터페이스 클래스에 대한 액세스를 제한합니다.
- 디바이스에 대해 만들어진 드라이버 서비스에 대한 액세스를 제한합니다.
- 드라이버 파일을 수정 또는 삭제로부터 보호합니다.
- 디바이스의 레지스트리 항목에 대한 액세스를 제한합니다.
- 디바이스의 WMI 클래스에 대한 액세스를 제한합니다.
- SetupAPI 함수를 올바르게 사용
자세한 내용은 다음을 참조하세요.
디바이스 설치 함수를 사용하기
기술별 코드 모범 사례 따르기
보안 검사 목록 항목 #8:드라이버에 대한 다음 기술별 지침을 검토합니다.
파일 시스템
파일 시스템 드라이버 보안에 대한 자세한 내용은 다음을 참조하세요.
파일 시스템 보안 소개
파일 시스템 대한 보안 기능
Microsoft 바이러스 이니셔티브
MVI(Microsoft 바이러스 이니셔티브)는 조직이 고객이 안전하게 유지하기 위해 사용하는 보안 솔루션을 개선하는 데 도움이 됩니다. Microsoft는 뛰어난 성능, 안정성 및 호환성을 갖춘 더 나은 환경을 지원하기 위한 도구, 리소스 및 지식을 제공합니다. Microsoft는 MVI 파트너와 협력하여 SDP(Safe Deployment Practices)를 정의하고 준수하여 상호 고객의 안전과 복원력을 지원합니다.
바이러스 백신 공급업체인 경우 소프트웨어 배포에 대한 추가 지원을 위해 MVI에 가입하는 방법을 알아보려면 Microsoft 바이러스 이니셔티브 참조하세요. 보안 공급업체가 보안 및 안정성 향상을 위해 Windows의 통합 보안 기능을 더 잘 활용하는 방법에 대한 자세한 내용은 보안 도구통합 및 관리하기 위한
NDIS - 네트워킹
NDIS 드라이버 보안에 대한 자세한 내용은 네트워크 드라이버 보안 문제를 참조하세요.
프린터
프린터 드라이버 보안과 관련된 자세한 내용은 V4 프린터 드라이버 보안 고려 사항참조하세요.
WIA(Windows 이미지 취득) 드라이버에 대한 보안 문제
WIA 보안에 대한 정보는 Windows 이미지 취득(WIA) 드라이버 보안 문제를 참조하세요.
드라이버 코드에 SAL 주석 추가
보안 검사 목록 항목 #9:드라이버 코드에 SAL 주석을 추가합니다.
SAL(소스 코드 주석 언어)은 함수가 매개 변수를 사용하는 방법, 매개 변수에 대해 가정하는 방법 및 완료 시 보장을 설명하는 데 사용할 수 있는 주석 집합을 제공합니다. 주석은 헤더 파일 sal.h
에서 정의되어 있습니다. C++용 Visual Studio 코드 분석은 SAL 주석을 사용하여 함수 분석을 수정합니다. Windows 드라이버 개발에 대한 SAL 2.0에 대한 자세한 정보는 Windows 드라이버용 SAL 2.0 주석을 참조하고, SAL 주석을 사용하여 C/C++ 코드 결함을 줄이는 방법을 참조하세요.
SAL에 대한 일반적인 내용은 OSR에서 사용할 수 있는 이 문서를 참조하세요. SAL 주석 : 나는 아름답기 때문에 나를 미워하지 마십시오
피어 코드 검토를 진행하다
보안 검사 목록 항목 #10:다른 도구 및 프로세스로 발견할 수 없는 문제를 찾기 위해 피어 코드 리뷰를 수행하십시오
지식이 풍부한 코드 리뷰어를 찾아서 놓친 문제를 발견하도록 하세요. 눈의 두 번째 세트는 종종 당신이 간과 할 수있는 문제를 볼 수 있습니다.
코드를 내부적으로 검토할 적절한 직원이 없는 경우 이 목적을 위해 외부 도움말을 참조하세요.
위협 분석 수행
보안 검사 목록 항목 #11:기존 드라이버 위협 모델을 수정하거나 드라이버에 대한 사용자 지정 위협 모델을 만듭니다.
보안을 고려할 때 일반적인 방법은 가능한 공격 유형을 설명하려는 특정 위협 모델을 만드는 것입니다. 이 기술은 개발자가 드라이버에 대한 잠재적인 공격 벡터를 미리 고려하도록 강제하기 때문에 드라이버를 디자인할 때 유용합니다. 잠재적인 위협을 식별한 드라이버 개발자는 드라이버 구성 요소의 전반적인 보안을 강화하기 위해 이러한 위협을 방어하는 방법을 고려할 수 있습니다.
이 문서에서는 경량 위협 모델을 만들기 위한 드라이버별 지침인 드라이버
SDL(보안 개발 수명 주기) 모범 사례 및 관련 도구를 IHV 및 OEM에서 사용하여 제품의 보안을 향상시킬 수 있습니다. 자세한 내용은 OEM대한
CodeQL을 사용하여 드라이버 코드 확인
보안 검사 목록 항목 #12:CodeQL을 사용하여 드라이버 코드의 취약성을 확인합니다.
GitHub의 CodeQL은 의미 체계 코드 분석 엔진이며, 강력한 플랫폼과 함께 광범위한 보안 쿼리 제품군을 조합하여 드라이버 코드를 보호하는 데 유용한 도구가 됩니다. 자세한 내용은 CodeQL 및 정적 도구 로고 테스트참조하세요.
드라이버 검증 도구를 사용하여 취약성 확인
보안 검사 목록 항목 #13:드라이버 검증 도구를 사용하여 드라이버 코드의 취약성을 확인합니다.
드라이버 검증 도구는 인터페이스 규칙 집합과 운영 체제 모델을 사용하여 드라이버가 Windows 운영 체제와 올바르게 상호 작용하는지 여부를 결정합니다. 드라이버 검증 도구는 드라이버 코드에서 잠재적인 버그를 가리킬 수 있는 결함을 찾습니다.
드라이버 검증 도구는 드라이버의 실시간 테스트를 허용합니다. 드라이버 검증 도구는 Windows 커널 모드 드라이버 및 그래픽 드라이버를 모니터링하여 시스템을 손상할 수 있는 잘못된 함수 호출 또는 작업을 감지합니다. 연결된 디버거를 사용하면 OS 및 드라이버 코드 실행을 실시간으로 볼 수 있습니다. 드라이버 검증 도구는 Windows 드라이버에 다양한 스트레스와 테스트를 적용하여 부적절한 동작을 찾을 수 있습니다. 자세한 내용은 드라이버 검증 도구참조하세요.
드라이버 Verifer는 WDM 및 KMDF 드라이버 모두에서 작동합니다. 확인할 수 있는 항목에 대한 자세한 내용은 다음 항목을 참조하세요.
드라이버 검증 도구에서 사용할 수 있는 드라이버에 대한 자세한 내용은
- NDIS 드라이버에 대한 규칙
- Storport 드라이버에 대한 규칙
- 오디오 드라이버 규칙
- AVStream 드라이버에 대한 규칙
DV에 익숙해지려면 샘플 드라이버(예: 주요 토스터 샘플: https://github.com/Microsoft/Windows-driver-samples/tree/main/general/toaster/toastDrv/kmdf/func/featured) 중 하나를 사용할 수 있습니다.
하드웨어 호환성 프로그램 테스트를 사용하여 코드 확인
보안 검사 목록 항목 #14:보안 관련 하드웨어 호환성 프로그램 테스트를 사용하여 보안 문제를 확인합니다.
하드웨어 호환성 프로그램에는 코드 취약성을 찾는 데 사용할 수 있는 보안 관련 테스트가 포함되어 있습니다. Windows 하드웨어 호환성 프로그램은 Windows HLK(하드웨어 랩 키트)의 테스트를 활용합니다. HLK 디바이스 기본 사항 테스트는 명령줄에서 드라이버 코드를 실행하고 약점을 조사하는 데 사용할 수 있습니다. 디바이스 기본 사항 테스트 및 하드웨어 호환성 프로그램에 대한 일반적인 정보는 Windows 하드웨어 랩 키트참조하세요.
다음 테스트는 드라이버 코드에서 코드 취약성과 관련된 일부 동작을 확인하는 데 유용할 수 있는 테스트의 예입니다.
DF - 퍼지 길이가 0인 버퍼 FSCTL 테스트(안정성)
드라이버 검증 도구에 포함된 커널 동기화 지연 퍼지 사용할 수도 있습니다.
CHAOS(동시 하드웨어 및 운영 체제) 테스트는 다양한 PnP 드라이버 테스트, 디바이스 드라이버 퍼지 테스트 및 전원 시스템 테스트를 동시에 실행합니다. 자세한 내용은 CHAOS 테스트(디바이스 기본 사항)참조하세요.
디바이스 기본 사항 침투 테스트는 보안 테스트의 중요한 구성 요소인 다양한 형태의 입력 공격을 수행합니다. 공격 및 침투 테스트는 소프트웨어 인터페이스의 취약성을 식별하는 데 도움이 될 수 있습니다. 자세한 내용은 침투 테스트(디바이스 기본 사항)참조하세요.
이 문서에 설명된 다른 도구와 함께 Device Guard - 준수 테스트사용하여 드라이버가 HVCI와 호환되는지 확인합니다.
사용자 지정 및 도메인별 테스트 도구
사용자 지정 도메인별 보안 테스트 개발을 고려합니다. 추가 테스트를 개발하려면 소프트웨어의 원래 디자이너와 개발 중인 특정 유형의 드라이버에 익숙한 관련 없는 개발 리소스 및 보안 침입 분석 및 방지에 익숙한 한 명 이상의 사용자로부터 입력을 수집합니다.
BinSkim 및 SignTool과 같은 도구를 사용하여 드라이버 배송 준비 확인
보안 검사 목록 항목 #15:파트너 센터에 업로드되기 전에 BinSkim 및 SignTool과 같은 도구로 컴파일된 코드를 확인합니다.
BinSkim 및 SignTool과 같은 도구를 사용하여 Windows 업데이트를 사용하여 배포할 파트너 센터에 업로드되기 전에 이진 파일을 검사하여 컴파일된 코드를 확인합니다. 배포를 위해 컴파일된 이진 파일을 제출하기 전에 확인함으로써 추가적인 보호 계층을 제공합니다.
BinSkim
BinSkim은 잠재적으로 이진을 취약하게 만들 수 있는 코딩 및 빌드 사례를 식별할 수 있습니다. BinSkim은 다음을 확인합니다.
- 오래된 컴파일러 툴킷 사용 - 가능한 경우 바이너리는 최신 컴파일러 툴킷으로 컴파일하여 컴파일러 수준 및 OS에서 제공하는 보안 완화를 최대한 활용해야 합니다.
- 안전하지 않은 컴파일 설정 - 가능한 한 가장 안전한 설정으로 이진 파일을 컴파일하여 OS에서 제공하는 보안 완화를 활성화하고, 컴파일러 오류와 보고 가능한 경고를 최대화하는 것이 좋습니다.
- 서명 문제 - 서명된 이진 파일은 암호학적으로 강력한 알고리즘으로 서명해야 합니다.
BinSkim은 오픈 소스 도구이며 정적 분석 결과 교환 형식(SARIF) 형식을 사용하는 출력 파일을 생성합니다. BinSkim은 이전 BinScope 도구를 대체합니다.
BinSkim에 대한 자세한 내용은 BinSkim을 사용하여 이진 파일 및 BinSkim 사용자 가이드확인하세요.
SignTool
SignTool을 사용하여 릴리스 서명된 드라이버 파일을 확인합니다. 자세한 내용은
테스트 코드에 프로덕션 서명을 하지 말 것
보안 검사 목록 항목 #16:개발, 테스트 및 제조 목적으로 사용되는 커널 드라이버 코드에 프로덕션 코드 서명을 하지 마세요.
개발, 테스트 또는 제조에 사용되는 커널 드라이버 코드에는 보안 위험을 초래하는 위험한 기능이 포함될 수 있습니다. 이 위험한 코드는 Windows에서 신뢰할 수 있는 인증서로 서명해서는 안 됩니다. 위험한 드라이버 코드를 실행하기 위한 올바른 메커니즘은 UEFI 보안 부팅을 사용하지 않도록 설정하고 BCD "TESTSIGNING"을 사용하도록 설정하고 신뢰할 수 없는 인증서(예: makecert.exe생성됨)를 사용하여 개발, 테스트 및 제조 코드에 서명하는 것입니다.
신뢰할 수 있는 SPC(소프트웨어 게시자 인증서) 또는 WHQL(Windows 하드웨어 품질 랩) 서명으로 서명된 코드는 Windows 코드 무결성 및 보안 기술을 쉽게 무시할 수 없습니다. 코드를 신뢰할 수 있는 SPC 또는 WHQL 서명으로 서명하기 전에 먼저 신뢰할 수 있는 Kernel-Mode 드라이버 만들기지침을 따르는지 확인합니다. 또한 코드에는 아래 설명된 위험한 동작이 포함되어서는 안 됩니다.
위험한 동작의 예는 다음과 같습니다.
- 임의의 커널, 물리적 또는 디바이스 메모리를 사용자 모드에 매핑하는 기능을 제공합니다.
- 포트 입력/출력(I/O)을 포함하여 임의의 커널, 물리적 또는 디바이스 메모리를 읽거나 쓰는 기능을 제공합니다.
- Windows 액세스 제어를 우회하는 스토리지에 대한 액세스 제공
- 드라이버가 관리하도록 설계되지 않은 하드웨어 또는 펌웨어를 수정하는 기능을 제공합니다.
Windows 업데이트를 사용하여 적절한 릴리스 드라이버 서명 실행 및 드라이버 패키지 배포
보안 검사 목록 항목 #17:Windows 파트너 포털을 사용하여 Windows 업데이트를 통해 서명 및 배포할 드라이버 패키지를 제출합니다.
드라이버 패키지를 일반에 릴리스하기 전에 인증을 위해 패키지를 제출합니다. 자세한 내용은 성능 및 호환성 테스트 을 참조하고, 하드웨어 프로그램 시작하기 를 확인하세요.
드라이버 패키지 배포에는 Windows 업데이트를 사용하는 것이 좋습니다. Windows 업데이트는 드라이버 업데이트를 제공하는 데 사용해야 하는 강력하고 안전하며 전역적으로 확장된 규정 준수 배포 시스템을 제공합니다. 자세한 내용은 드라이버 패키지 배포 에 관한을 참조하세요.
Windows 하드웨어를 위한
안전한 소프트웨어 배포 사례에 대한 설명은 CISA 안전한 소프트웨어 배포: 소프트웨어 제조업체가 고객에게 안정성을 보장하는 방법참조하세요.
드라이버가 Microsoft 취약 및 악성 드라이버 보고 센터 를 사용하여 어떻게 보고되는지 이해합니다.
보안 검사 목록 항목 #18:Microsoft 취약 및 악성 드라이버 보고 센터 사용하여 드라이버를 보고하는 방법을 이해합니다.
누구나 Microsoft 취약 및 악성 드라이버 보고 센터
Reporting Center는 x86 및 x64 아키텍처용으로 빌드된 Windows 드라이버를 검색하고 분석할 수 있습니다. 취약한 드라이버와 악성 드라이버는 Microsoft의 취약한 드라이버 팀에서 분석 및 조사를 위해 식별됩니다. 취약한 드라이버가 확인되면 적절한 알림이 발생하며 취약한 드라이버 차단 목록에 추가됩니다. 자세한 내용을 보려면 Microsoft 권장 드라이버 블록 규칙을 참조하세요. 이러한 규칙은 기본적으로 HVCI(하이퍼바이저로 보호된 코드 무결성) 사용 디바이스 및 S 모드의 Windows 10에 적용됩니다.
보안 코딩 리소스 검토
보안 검사 목록 항목 #19:이러한 리소스를 검토하여 드라이버 개발자에게 적용되는 보안 코딩 모범 사례에 대한 이해를 확장합니다.
Microsoft NISTIR 8397 지침
미국 정부 간행물 NISTIR 8397: NIST(National Institute of Standards and Technology) 의한 소프트웨어 개발자 검증을 위한 최소 표준 지침에는 모든 프로그래밍 언어로 안정적이고 안전한 소프트웨어를 빌드하는 방법에 대한 지침이 포함되어 있습니다.
신뢰할 수 있고 안전한 C++ 프로그램 빌드 C++ 및 기타 언어에 Microsoft 개발자 제품을 사용하여 NISTIR 8397 지침을 따르는 방법을 요약합니다.
NIST 알려진 소프트웨어 취약성 데이터베이스
NVD(National Vulnerability Database)는 Windows 드라이버를 포함하여 보안 관련 소프트웨어 결함의 검색 가능한 리포지토리입니다.
보안 코딩 표준
Carnegie Mellon University SEI CERT - C 언어 코딩 표준: 안전하고 신뢰할 수 있으며 보안이 뛰어난 시스템 개발을 위한 규칙 (PDF).
MITRE - CERT C 보안 코딩 표준으로 해결된 약점
Microsoft Visual Studio - C++ 핵심 지침 검사기 사용
보안 코딩 조직
OSR
OSR 드라이버 개발 교육 및 컨설팅 서비스를 제공합니다. OSR 뉴스레터의 이러한 문서는 드라이버 보안 문제를 강조 표시합니다.
이름, 보안 설명자 및 디바이스 클래스 - 액세스할 수 있는 디바이스 개체 만들기... 및 안전
보호를 반드시 사용해야 합니다 - 드라이버 & 장치 보안 내부
드라이버 잠금 - 기술에 대한 설문 조사
Meltdown과 Spectre: 드라이버는 어떻게 되나요?
드라이버 취약성 사례 연구
경고에서 드라이버 취약성까지: Microsoft Defender ATP 조사를 통해 발견된 권한 에스컬레이션 결함
소프트웨어 공급망 보안 및 SBOM(Software Bill of Materials)
SBOM은 오픈 소스 소프트웨어, 구성 요소 및 잠재적으로 빌드 도구와 같은 소프트웨어를 만드는 데 사용되는 재료 목록을 제공합니다. 이를 통해 생산자와 소비자는 더 나은 인벤토리를 제공하고 라이선스 및 취약성 위험을 평가할 수 있습니다. Microsoft는 SPDX(소프트웨어 패키지 데이터 교환) SBOM 문서 형식으로 사용하고 있습니다. 자세한 내용은 Microsoft에서 SPDX를 사용하여 소프트웨어 청구서(SBOM)를 생성하는 방법과 Microsoft가 소프트웨어 청구서(SBOM) 생성 도구를 오픈 소스로 공개한 내용을 참조하세요.
SCITT(공급망 무결성, 투명성 및 신뢰) 이니셔티브 엔드투엔드 공급망에서 상품 및 서비스의 규정 준수를 관리하기 위한 일련의 IETF 인터넷 표준입니다. SCITT는 엔터티, 증거, 정책 및 아티팩트의 신뢰성을 보장하며, 엔터티의 행위가 승인되고, 부인할 수 없으며, 변경 불가능하고 감사 가능한 상태를 보장하여 상품 및 서비스의 지속적인 검증을 지원합니다.
책
소프트웨어 보안의 24가지 치명적인 죄악: 프로그래밍 결함과 이를 해결하는 방법 | 마이클 하워드, 데이비드 르블랑, 존 비에가 저
보안 소프트웨어 작성, 제2판, 마이클 하워드와 데이비드 르블랑
소프트웨어 보안 평가의 예술:소프트웨어 취약성 식별 및 방지, Mark Dowd, John McDonald 및 Justin Schuh
C 및 C++의 보안 코딩(소프트웨어 엔지니어링의 SEI 시리즈) 제2판, Robert C. Seacord
Microsoft Windows 드라이버 모델 프로그래밍 (2판), Walter Oney
Windows 드라이버 파운데이션(개발자 참조), Penny Orwick 및 Guy Smith를 사용하여 드라이버 개발
훈련
Windows 드라이버 클래스룸 교육은 다음과 같은 공급업체에서 사용할 수 있습니다.
보안 코딩 온라인 교육은 다양한 소스에서 사용할 수 있습니다. 예를 들어 이 과정은 다음의 coursera에서 사용할 수 있습니다.
C/C++ 프로그래밍보안 취약성을 식별합니다.
SAFECode는 다음과 같은 무료 교육도 제공합니다.
전문 인증
CERT는 보안 코딩 전문 인증제공합니다.
주요 내용 요약
드라이버 보안은 많은 요소를 포함하는 복잡한 작업이지만 고려해야 할 몇 가지 주요 사항은 다음과 같습니다.
드라이버는 Windows 커널에 있으며 커널에서 실행할 때 문제가 발생하면 전체 운영 체제가 노출됩니다. 이 때문에 보안을 염두에 두고 드라이버 보안 및 설계에 세심한 주의를 기울여야 합니다.
최소 권한 원칙을 적용합니다.
a. 엄격한 SDDL 문자열을 사용하여 드라이버에 대한 액세스를 제한합니다.
b. 개별 IOCTL을 더 제한하기
위협 모델을 만들어 공격 벡터를 식별하고 추가로 제한할 수 있는지 여부를 고려합니다.
사용자 모드에서 전달되는 내재된 포인터에 주의해야 합니다. 그들은 탐색되고 try-except 구문 내에서 접근되어야 하며, 버퍼의 값을 캡처하고 비교하지 않으면 사용 시간 검사 시간(ToCToU) 문제에 취약합니다.
확실하지 않은 경우 METHOD_BUFFERED를 IOCTL 버퍼링 방법으로 선택하세요.
CodeQL과 같은 코드 검사 유틸리티를 사용하여 알려진 코드 취약성을 찾고 식별된 문제를 해결합니다.
지식이 풍부한 코드 리뷰어를 찾아서 놓친 문제를 발견하도록 하세요.
드라이버 검증기를 사용하고 코너 케이스를 포함하여 여러 입력을 사용하여 드라이버를 테스트하세요.