
Prova de conceito para CVE-2021-28476, uma desreferência arbitrária de ponteiro em vmswitch.sys do Hyper-V que permite negação de serviço do convidado para o host e possível RCE.
Uma máquina virtual convidada do Hyper-V pode acionar uma condição de Negação de Serviço no host subjacente devido à análise insegura de entrada pela função VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST em vmswitch.sys. A falha é causada pela função tentar desreferenciar um valor controlado pelo convidado como se fosse um endereço virtual do host. Este bug pode ser usado para obter RCE sob algumas condições, nomeadamente quando a solicitação é passada para um dispositivo de hardware subjacente com um ponteiro para dados controlados pelo atacante, porém não tenho conhecimento de que esta técnica tenha sido demonstrada publicamente.
11 de maio de 2021
https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-28476
Desreferência Arbitrária
Engenharia Reversa/Auditoria de Código
Este bug foi encontrado durante meu reconhecimento inicial do driver vmswitch. Ao revisar a documentação no MSDN, foi observado que a struct NDIS_SWITCH_NIC_OID_REQUEST continha um ponteiro, e lembrei de ter visto uma referência ao nome da struct em um nome de função. Alguma engenharia reversa foi realizada para tentar entender como a função poderia operar, dado que um convidado não deveria ter qualquer conhecimento do VA do host, mas nenhuma verificação de segurança real estava presente. Um driver Linux do Hyper-V modificado foi então usado para enviar uma solicitação falsa ao host, acionando imediatamente uma falha.
O driver vmswitch.sys contém uma série de funções para lidar com solicitações OID RNDIS, incluindo algumas especificamente para registrar mensagens recebidas. Uma delas, VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST, lida com solicitações do tipo OID_SWITCH_NIC_REQUEST. De acordo com a documentação do MSDN, esta solicitação é projetada para permitir o encaminhamento de solicitações OID de uma máquina convidada para um adaptador de rede físico subjacente através do adaptador de rede externo do switch extensível do Hyper-V.
As solicitações OID usam uma estrutura de mensagem genérica bem definida para sua camada externa, que inclui um "InformationBuffer" projetado para armazenar dados específicos de um tipo de mensagem OID. No caso de OID_SWITCH_NIC_REQUEST, o InformationBuffer tem a seguinte definição (observe que difere ligeiramente da estrutura documentada, mas corresponde ao que estava funcionalmente presente no código):
typedef struct _NDIS_SWITCH_NIC_OID_REQUEST {
NDIS_OBJECT_HEADER Header; //struct de tamanho u32
u32 Flags;
NDIS_SWITCH_PORT_ID SourcePortId; //tipo u32
NDIS_SWITCH_PORT_NIC SourceNicIndex; //tipo u32
NDIS_SWITCH_PORT_ID DestinationPortId; //tipo u32
NDIS_SWITCH_PORT_NIC DestinationNicIndex; //tipo u32
PNDIS_OID_REQUEST OidRequest; //**deveria** ser um ponteiro para uma estrutura NDIS_OID_REQUEST encaminhada
} NDIS_SWITCH_NIC_OID_REQUEST, *PNDIS_SWITCH_NIC_OID_REQUEST;
Como parte da análise inicial deste objeto, VmsIfrInfoParams_OID_SWITCH_NIC_REQUEST tentará desembrulhar a solicitação NDIS_OID_REQUEST encaminhada da _NDIS_SWITCH_NIC_OID_REQUEST encapsuladora. No entanto, se um convidado do Hyper-V fornecer um local de memória inválido como o valor de OidRequest, a desreferência causará uma leitura fora dos limites e travará o kernel da partição raiz.
O pseudo-código da função afetada é o seguinte:
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; //desreferência e falha ocorrem aqui
}
}
...
//truncado
...
return;
}