
CVE-2021-28476에 대한 개념 증명(PoC)으로, Hyper-V vmswitch.sys의 임의 포인터 역참조 취약점으로 게스트에서 호스트로의 서비스 거부(DoS) 및 잠재적 원격 코드 실행(RCE)을 허용합니다.
Hyper-V 게스트 가상 머신은 vmswitch.sys의 VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST 함수가 입력을 안전하지 않게 파싱하여 기본 호스트에서 서비스 거부(Denial-of-Service) 조건을 유발할 수 있습니다. 이 크래시는 함수가 게스트가 제어하는 값을 호스트 가상 주소인 것처럼 역참조하려고 시도하기 때문에 발생합니다. 이 버그는 특정 조건, 즉 요청이 공격자가 제어하는 데이터에 대한 포인터와 함께 기본 하드웨어 장치로 전달되는 경우 RCE를 얻는 데 사용될 수 있지만, 이 기술이 공개적으로 시연된 사례는 알려져 있지 않습니다.
2021년 5월 11일
https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-28476
임의 역참조(Arbitrary Dereference)
리버스 엔지니어링/코드 감사
이 버그는 vmswitch 드라이버에 대한 초기 정찰 중에 발견되었습니다. MSDN의 문서를 검토하는 동안 NDIS_SWITCH_NIC_OID_REQUEST 구조체에 포인터가 포함되어 있다는 것을 확인했고, 함수 이름에서 해당 구조체 이름에 대한 참조를 본 것을 기억했습니다. 게스트가 호스트 VA에 대한 정보를 알 수 없어야 하지만 실제 안전 검사가 없었기 때문에 함수가 어떻게 작동할 수 있는지 이해하기 위해 일부 리버스 엔지니어링을 수행했습니다. 그런 다음 수정된 Linux Hyper-V 드라이버를 사용하여 호스트에 가짜 요청을 보내 즉시 크래시를 유발했습니다.
vmswitch.sys 드라이버에는 RNDIS OID 요청을 처리하는 여러 함수가 포함되어 있으며, 그중 일부는 수신 메시지를 기록하기 위한 것입니다. 그중 하나인 VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST는 OID_SWITCH_NIC_REQUEST 유형의 요청을 처리합니다. MSDN 문서에 따르면 이 요청은 Hyper-V 확장 가능 스위치 외부 네트워크 어댑터를 통해 게스트 머신에서 기본 물리적 네트워크 어댑터로 OID 요청을 전달할 수 있도록 설계되었습니다.
OID 요청은 외부 계층에 대해 잘 정의된 일반 메시지 구조를 사용하며, 여기에는 특정 OID 메시지 유형에 대한 데이터를 보관하도록 설계된 "InformationBuffer"가 포함됩니다. OID_SWITCH_NIC_REQUEST의 경우 InformationBuffer는 다음과 같은 정의를 갖습니다(문서화된 구조와 약간 다르지만 코드에 기능적으로 존재하는 것과 일치함):
typedef struct _NDIS_SWITCH_NIC_OID_REQUEST {
NDIS_OBJECT_HEADER Header; //u32 크기 구조체
u32 Flags;
NDIS_SWITCH_PORT_ID SourcePortId; //u32 유형
NDIS_SWITCH_PORT_NIC SourceNicIndex; //u32 유형
NDIS_SWITCH_PORT_ID DestinationPortId; //u32 유형
NDIS_SWITCH_PORT_NIC DestinationNicIndex; //u32 유형
PNDIS_OID_REQUEST OidRequest; //**이어야 하는** 전달된 NDIS_OID_REQUEST 구조체에 대한 포인터
} NDIS_SWITCH_NIC_OID_REQUEST, *PNDIS_SWITCH_NIC_OID_REQUEST;
이 객체의 초기 파싱의 일부로, VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST는 캡슐화된 _NDIS_SWITCH_NIC_OID_REQUEST에서 전달된 NDIS_OID_REQUEST 요청을 풀려고 시도합니다. 그러나 Hyper-V 게스트가 OidRequest 값으로 잘못된 메모리 위치를 제공하면 역참조로 인해 범위를 벗어난 읽기(out-of-bounds read)가 발생하고 루트 파티션 커널이 크래시됩니다.
영향을 받는 함수의 의사 코드는 다음과 같습니다:
void VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST(void* unknown1, u64 unknown2, _NDIS_SWITCH_NIC_OID_REQUEST* request, u32 buffer_size) {
NDIS_OID_REQUEST* forwarded_request;
if((unknown1 != 0) && (buffer_size != 0)) {
if(buffer_size > 0x20) {
forwarded_request = (NDIS_OID_REQUEST*)request->OidRequest; //역참조 및 크래시가 여기서 발생
}
}
...
//생략됨
...
return;
}