Silenciar o som: Encadeamento de vulnerabilidades para obter RCE no Outlook: Parte 1
Resumo executivo
O pesquisador da Akamai, Ben Barnea, encontrou duas vulnerabilidades no Microsoft Windows, que foram atribuídas a CVE-2023-35384 e CVE-2023-36710.
Um invasor na Internet pode encadear as vulnerabilidades para criar uma exploração completa de execução remota de código (RCE) com zero clique contra clientes do Outlook.
A primeira vulnerabilidade está na análise de um caminho pela MapUrlToZone . A exploração desta vulnerabilidade requer o envio de um e-mail criado para um cliente do Outlook, que, por sua vez, fará o download de um arquivo de som especial de um servidor controlado por invasor.
A segunda vulnerabilidade está no Gerenciador de Compactação de Áudio (ACM). Essa vulnerabilidade é explorada quando o arquivo de som baixado é reproduzido automaticamente e pode levar à execução de código na máquina vítima. Essa vulnerabilidade é descrita em detalhes na parte 2 desta publicação do blog.
As vulnerabilidades foram divulgadas de forma responsável para a Microsoft e abordadas em 2023 de agosto e outubro de 2023 nas Patch Tuesdays.
Os computadores Windows com a atualização de software de outubro de 2023 instalada estão protegidos contra essas vulnerabilidades. Além disso, os clientes Outlook que utilizam servidores Exchange atualizados com a atualização de software de março de 2023 estão protegidos contra o uso indevido dessa funcionalidade.
Visão geral
Entre as vulnerabilidades abordadas como parte do Patch Tuesday de março de 2023 havia uma vulnerabilidade crítica do Outlook designada CVE-2023-23397que foi explorada livremente pela Forest Blizzard, que a Microsoft identificou como um agente de ameaças patrocinado pelo estado russo. Em dezembro de 2023, a Microsoft, juntamente com o Polish Cyber Command (DKWOC), divulgou que eles tinham visto tentativas recentes de exploração da vulnerabilidade pelo mesmo agente de ameaças. A vulnerabilidade permitia que um invasor coagisse um cliente Outlook a se conectar ao servidor do invasor. Como parte dessa conexão, o cliente envia suas credenciais NTLM para o invasor, que pode decifrá-las off-line ou usá-las em um ataque de retransmissão. Essa vulnerabilidade poderia ser explorada remotamente pela Internet sem nenhuma interação do usuário (clique zero).
Após o lançamento do patch para essa vulnerabilidade, encontramos um desvio descrito na publicação anterior no blog. Esse desvio foi corrigido na Patch Tuesday de maio de 2023. Naquela publicação, recomendamos que a Microsoft removesse o recurso abusivo, pois ele introduz uma superfície de ataque vasta e complexa. Como o recurso permanece no Outlook, decidimos investigá-lo ainda mais.
Por fim, conseguimos atingir uma cadeia completa de vulnerabilidades de RCE no Outlook. Encontramos outro desvio para a vulnerabilidade original do Outlook: um desvio que mais uma vez nos permitiu coagir o cliente a se conectar a um servidor controlado por invasor e baixar um arquivo de som mal-intencionado. Em seguida, conseguimos encontrar uma vulnerabilidade na biblioteca de análise de mídia do Windows que é usada para processar e reproduzir qualquer arquivo de áudio em geral e os sons de notificação do Outlook em particular. Um invasor encadeando essas vulnerabilidades pode alcançar um RCE de clique zero em clientes vulneráveis do Outlook.
Esta série de publicações em duas partes do blog apresentará a pesquisa que realizamos para encontrar as duas vulnerabilidades. A primeira parte se concentrará no desvio anterior e em uma nova. Em parte 2descreveremos a vulnerabilidade de análise de mídia que encontramos.
A vulnerabilidade original
A vulnerabilidade do Outlook que foi corrigida em março é acionada quando um invasor envia um e-mail contendo um lembrete com um som de notificação personalizado. Esse som personalizado é especificado pelo invasor como um caminho, usando a propriedade MAPI PidLidReminderFileParameter. Um invasor pode especificar um caminho UNC que faria com que o cliente recuperasse o arquivo de som de qualquer servidor SMB. Como parte da conexão com o servidor SMB remoto, o hash Net-NTLMv2 é enviado em uma mensagem de negociação (Figura 1).
Para corrigir o problema, o código agora chama MapUrlToZone para classificar o caminho como intranet, local ou internet. Se o URL apontar para um recurso na Internet, o som de lembrete padrão será usado em vez do personalizado.
Localizar um desvio
Depois que a mitigação foi implementada, nos perguntamos se era possível desviá-la.
Nesse contexto, um desvio significa um caminho que passará no teste de localidade e será usado pelo Outlook para baixar o arquivo de som de um local remoto. Em outras palavras, precisamos encontrar um caminho que a MapUrlToZone considere como não pertencente à Internet, mas que a CreateFile trate como um domínio da Internet.
Para encontrar esse desvio, precisávamos entender completamente o funcionamento interno das funções e as operações realizadas como parte da análise do caminho.
Caminhos e URLs do Windows
Há muitas versões diferentes de caminhos DOS no Windows, e muitas pesquisas foram realizadas sobre eles e sua conversão para caminhos do NT. Não cobriremos os diferentes tipos de caminho do Windows aqui. A publicação no blog de James Forshaw aborda este tópico em detalhes.
Vamos voltar às nossas funções de interesse. CreateFile recebe um caminho do Windows; MapUrlToZone (conforme o nome sugere) pode ser passado um URL ou um caminho. Para encontrar um desvio, primeiro precisamos entender quais tipos de caminho são suportados por cada função (ou ambas).
Observação: CreateFile e MapUrlToZone não processam os próprios caminhos,; em vez disso, eles usam outras funções WinAPI para essa finalidade. Para sermos breves, utilizaremos CreateFile e MapUrlToZone para nos referirmos às suas funções de análise de caminho subjacentes.
CreateFile |
MapUrlToZone |
|
---|---|---|
RtlPathTypeUncAbsolute |
✔ |
✔ |
RtlPathTypeDriveAbsolute |
✔ |
✔ |
RtlPathTypeDriveRelative |
✔ |
✔ |
RtlPathTypeRooted |
✔ |
✘ |
RtlPathTypeRelative |
✔ |
✘ |
RtlPathTypeLocalDevice |
✔ |
✔ |
RtlPathTypeRootLocalDevice |
✔ |
✘ |
Schemes (file://, http://) |
✘ |
✔ |
Tabela 1: Gráfico de comparação de CreateFile e MapUrlToZone recursos de caminho
Como visto na Tabela 1, apenas quatro tipos de caminho são suportados por ambas as funções: RtlPathTypeUncAbsolute, RtlPathTypeDriveAbsolute, RtlPathTypeDriveRelative e RtlPathTypeLocalDevice.
Primeira tentativa
A primeira tentativa de localizar um desvio foi com um caminho UNC absoluto (RtlPathTypeUncAbsolute). A Figura 2 detalha a estrutura do caminho.
Como o Windows sabe onde o componente caminho começa? A Tabela 2 mostra o código relevante (RtlGetFullPathName_Ustr).
case RtlPathTypeUncAbsolute:
SeperatorsFound = 0;
for ( CurrentIndex = 2; CurrentIndex < InputPathLength; ++CurrentIndex )
{
CurrentChar = InputPathString->Buffer[CurrentIndex];
if ( CurrentChar == '\\' || CurrentChar == '/' )
{
SeperatorsFound++;
if ( SeperatorsFound == 2 )
break;
}
}
Tabela 2: RtlGetFullPathName_Ustr snippet de código que está manipulando o caminho UNC
Podemos ver que o código ignora o prefixo UNC absoluto ("\\") e, em seguida, assume que o componente do caminho começa um caractere após o segundo separador de caminho ("\" ou "/").
Mas o que acontece se fornecermos um caminho como "\\\\localhost\..\Akamai.com\dir\file.txt"?
O caminho será processado da seguinte forma:
"\\\\" é interpretado como o prefixo UNC e o componente do caminho raiz
O componente de caminho é "localhost\..\Akamai.com\dir\file.txt"
Normalmente, nenhuma quantidade de "..." poderia ir além do caminho raiz. Por exemplo, "\\localhost\directory\..\file.txt" resultaria em "\\localhost\directory\file.txt". No entanto, como em nosso exemplo o "..." não faz parte do caminho raiz, o caminho é convertido em "\\\\Akamai.com\dir\file.txt".
Isso significa que descobrimos uma maneira de adulterar o caminho, eliminando partes dele.
É assim que o CreateFile processa esse caminho. Como o MapUrlToZone faz (Tabela 3)? Primeiro, ele remove as barras invertidas extras e, portanto, interpreta o caminho de uma maneira diferente:
\\localhost é o nome do servidor
\..\ é ignorado (pois não podemos ir além do nome do servidor)
Akamai.com\dir\file.txt inclui o componente de caminho
Caminho de entrada: \\\\localhost\..\Akamai.com/pt\dir\file.txt |
|
---|---|
CreateFile |
MapUrlToZone |
\\\Akamai.com\dir\file.txt |
\\localhost\Akamai.com\dir\file.txt |
Tabela 3: Caminhos de entrada para CreateFile e MapUrlToZone e o resultado da análise
MapUrlToZone retorna 0 (Local) para o caminho de saída visto acima.
Embora pareça que encontramos um desvio, infelizmente, o caminho não pode ser usado para acionar uma solicitação UNC. Observe a barra extra no início do caminho processado pelo CreateFile – isso marca o nome do servidor como vazio. Quando o provedor de múltiplas UNC (MUP) consulta os diferentes provedores de rede para saber se eles podem lidar com esse nome de servidor (vazio), todos eles retornam falso, portanto, nenhuma solicitação é feita.
Abusar da diferença entre a forma como o MapUrlToZone e CreateFile tratam esse caminho pode exigir uma solução mais complicada, talvez como encontrar uma forma de omitir a barra invertida adicional ou encontrar uma incompatibilidade de análise no código do MUP. Esta é uma sugestão para pesquisas futuras.
Segunda tentativa: Desvio nº 1 (CVE-2023-29324)
Como brincar com caminhos UNC absolutos não funcionou, passamos para o próximo tipo de caminho que suporta UNC – RtlPathTypeLocalDevice. "\\.\UNC\Akamai.com\test.wav" é um exemplo de caminho de dispositivo local. Especificamente, ele aponta para o nome do dispositivo UNC, que será redirecionado para o driver MUP.
Conforme orientado anteriormente, para encontrar um desvio, precisamos olhar para as diferentes operações feitas como parte da análise dos caminhos. A Tabela 4 ilustra essa diferença.
CreateFile |
MapUrlToZone |
---|---|
se RtlPathTypeLocalDevice → Avance 4 caracteres |
se RtlPathTypeLocalDevice → Avance 4 caracteres |
Ignorar espaços à direita |
|
Converter ‘/’ para ‘\’ |
|
Recolher ‘\’ repetidos |
|
Remover '.' e componentes '..' |
Remover '.' e componentes '..' |
Tabela 4: Diferentes operações concluídas como parte da análise de caminhos
Podemos ver que a CreateFile realiza operações extras, como a conversão de barras em barras invertidas e o recolhimento de barras invertidas repetidas.
Vamos dar uma olhada em um caminho que aproveita uma dessas diferenças , usando um separador de caminho extra. A Tabela 5 mostra os caminhos resultantes depois que o código ignora o prefixo "UNC\".
Caminho de entrada: \\.\UNC\\Akamai.com\test.wav |
|
---|---|
CreateFile |
MapUrlToZone |
Akamai.com\test.wav |
\Akamai.com\test.wav |
Tabela 5: Caminhos resultantes após ignorar o prefixo UNC/
Observe o caminho na coluna da direita. Um caminho que começa com um separador de caminho seguido por um caractere que não é um separador de caminho é chamado de caminho raiz. MapUrlToZone usa as funções IsRootedPath ou IsDrivePath para determinar se o componente do caminho raiz é local. Em nosso caso, o caminho está enraizado e, portanto, o MapUrlToZone retorna localmente.
A CreateFile não tem o separador de caminho extra após o prefixo UNC, portanto, ele sabe extrair o nome de domínio corretamente e agora acessa o servidor SMB da Akamai.com para recuperar o arquivo test.wav. Encontramos um caminho que o MapUrlToZone considera local, mas o CreateFile não. Esse desvio reativou a exploração da vulnerabilidade do Outlook CVE-2023-23397.
Para atenuar esse problema, a Microsoft tentou tornar os dois fluxos mais semelhantes; as operações de conversão de barras para barras invertidas e recolhimento de separadores de caminho repetidos agora foram adicionadas ao fluxo de análise de caminho do MapUrlToZone.
Uma ideia...
Na seção anterior, observamos que o MapUrlToZone verifica se o componente do caminho após "\\.\UNC\" é uma unidade ou um caminho enraizado. Não podemos tornar este componente de caminho um caminho raiz após a correção porque os separadores de caminho repetidos estão recolhidos. No entanto, ainda podemos fornecer um caminho de unidade, por exemplo, "\\.\UNC\C:Akamai.com/test.wav".
Isso de fato faz com que o MapUrlToZone retorne 0. Infelizmente, nenhum provedor de rede é capaz de lidar com um caminho com dois pontos nele, portanto, essa confusão não é útil para nós. Assim como em nossa primeira tentativa (falha), encontrar uma confusão com o código de análise MUP pode levar a uma nova vulnerabilidade.
Terceira tentativa: Desvio nº 2 (CVE-2023-35384)
Após a correção, as operações realizadas pelas duas funções são quase as mesmas (Tabela 6).
CreateFile |
MapUrlToZone |
---|---|
se RtlPathTypeLocalDevice → Avance 4 caracteres |
Se RtlPathTypeLocalDevice → Avance 4 caracteres |
Ignorar espaços à direita |
|
Converter ‘/’ para ‘\’ |
Converter ‘/’ para ‘\’ |
Recolher ‘\’ repetidos |
Recolher ‘\’ repetidos |
Remover '.' e componentes '..' |
Remover '.' e componentes '..' |
Tabela 6: Operações realizadas pelo A CreateFile CreateFile e do MapUrlToZone
No entanto, se nos aprofundarmos nos detalhes, podemos nos perguntar: Como cada função decide se o caminho é um caminho de dispositivo local? A Tabela 7 ilustra fragmentos de código de cada função que ajudam a determinar o tipo de caminho.
CreateFile
if (IS_PATH_SEPARATOR(Path[0]) &&
IS_PATH_SEPARATOR(Path[1]) &&
(Path[2] == '.' || Path[2] == '?') &&
IS_PATH_SEPERATOR(Path[3])
return RtlPathTypeLocalDevice;
MapUrlToZone
!strncmp(path, "\\.\", 4) || !strncmp(path, "\\?\", 4)
Tabela 7: Snippets de código que determinam o tipo de caminho
Com a A CreateFileum separador de caminho pode ser uma barra ou uma barra invertida; por exemplo, "\\./" é considerado um caminho de dispositivo local. Com a MapUrlToZone,apenas os caminhos exatos " ou "?" são considerados caminhos de dispositivo local. Trata-se de uma confusão de tipo de caminho. Podemos fazer a CreateFile reconhecer o componente "\\./" como um caminho de dispositivo local enquanto a MapUrlToZone não. Essa confusão envolve o manuseio diferente do caminho pelas duas funções.
Com isso em mente, vamos usar um caminho que contenha o componente "confuso": \\./UNC/Akamai.com/file.wav.
Ao analisar a tomada de decisão para o tipo desse caminho, esse é o fluxo doMapUrlToZone:
O caminho é uma unidade local ou um caminho raiz? Não
IsLocalDeviceUNC? Não
PathIsUNCW? Sim
O PathIsUNCW retorna como verdadeiro e, portanto, a função o marca como um caminho UNC absoluto e avança dois caracteres para ignorar o prefixo UNC "\\". A saída para cada função é mostrada na Tabela 8.
Caminho de entrada: \\./UNC/Akamai.com/file.wav |
|
---|---|
CreateFile |
MapUrlToZone |
UNC\Akamai.com\file.wav |
./UNC/Akamai.com/file.wav |
Tabela 8: Saídas de caminhos A CreateFile CreateFile e MapUrlToZone
Neste ponto, a CreateFile conclui que sua saída é um caminho UNC e que Akamai.com é o nome do host.
Por outro lado, MapUrlToZone conclui as seguintes informações:
Esquema: file://
Host: . (ponto)
Caminho: /UNC/Akamai.com/file.wav
URI absoluto: arquivo://./UNC/Akamai.com/file.wav
Acontece que quando o URI absoluto começa com "file://./" (com o host sendo "."), o código interpreta o sharename como parte do namespace dos dispositivos DOS (Figura 3). Assim, "file://./UNC/" refere-se ao namespace do UNC.
Para esclarecer, ambas as funções consideram nosso caminho de entrada um caminho UNC, mas de um tipo diferente: CreateFile trata-o como um caminho de dispositivo local do Windows, enquanto a MapUrlToZone o vê como um URL.
Nesse ponto, podemos desencadear uma confusão entre as duas funções. Infelizmente, se não fizermos nenhum truque, a MapUrlToZone ainda interpretaria Akamai.com como o nome de host, e como esse nome de host é um domínio da Internet, a função retornará 3, portanto, não se trata de um desvio. Precisamos encontrar outra maneira de abusar do processo de análise.
Mais tarde, a MapUrlToZone usa uma função interna chamada SetPath para operar no componente do caminho (Tabela 9).
CreateFile |
SetPath |
---|---|
se RtlPathTypeLocalDevice → Avance 4 caracteres |
|
Ignorar espaços à direita |
|
Converter ‘/’ para ‘\’ |
|
Recolher ‘\’ repetidos |
|
Remover '.' e componentes '..' |
Remover '.' e componentes '..' |
Tabela 9: Comparação das operações concluídas entre CreateFile e SetPath
Mais uma vez, podemos aproveitar a diferença entre as operações realizadas pelas duas funções. Sabemos, com base em nossa vulnerabilidade anterior, que a adição de uma barra extra pode levar a um desvio, por isso faz sentido tentar novamente. A CreateFile simplesmente removerá a barra extra.
Com oMapUrlToZone, o CreateUri retorna o URI absoluto "file://./UNC//Akamai.com/file.wav". Este URI é passado para o GetZoneFromUriInternal,que conduz internamente a outra chamada CreateUri.
E por que isso é um problema? Como o CreateUri recebeu um URL, ele o converte de volta para um caminho do Windows usando o PathCreateFromUrlW. O caminho retornado do Windows é "\\.\UNC\\Akamai.com\test.wav”. A versão fixa agora sabe remover a barra extra e, portanto, entende corretamente que Akamai.com é o nome do host.
Isso significa que precisamos de um abuso mais complicado da diferença entre CreateFile e SetPath. Desta vez, abusaremos de duas diferenças:
A CreateFile recolhe separadores de caminho repetidos.
A CreateFile remove os componentes "." e ".." depois do colapso dos separadores de caminho repetidos.
Um caminho que abusa das duas diferenças é \\./UNC/C://../Akamai.com/file.wav. O processamento é detalhado no fluxograma da Figura 4.
Fig. 4: Fluxograma do caminho que está sendo analisado pelas duas funções
Já sabemos que A CreateFileserá tratado como um caminho UNC. Quanto à saída do SetPath,a MapUrlToZone chamará o GetZoneFromUriInternal com o URI absoluto file://./UNC/C:/Akamai.com/file.wav. Desta vez, o PathCreateFromUrlW converte esse URL para o caminho do Windows "\\.\UNC\C:\Akamai.com\file.wav". Este é um caminho local e, portanto, a MapUrlToZone retorna 0 (local). Mais uma vez encontramos um desvio perfeito!
Para corrigir o problema, o código agora chama NormalizeDosDevicePrefix para converter barras em barras invertidas, evitando confusão na detecção de um caminho de dispositivo local.
Detecção e mitigação
A Microsoft publicou uma orientação abrangente para a detecção e atenuação da vulnerabilidade original do Outlook. A partir da nossa observação, todos os métodos especificados são aplicáveis à nova vulnerabilidade, pois não dependem do URL especificado na propriedade PidLidReminderFileParameter .
Recomendamos que as organizações usem microssegmentação para bloquear conexões SMB de saída para endereços IP públicos remotos. Além disso, recomendamos que você desative o NTLM em seu ambiente ou adicione usuários ao Grupo de Segurança de usuários,que impede o uso do NTLM como um mecanismo de autenticação.
Bloquear conexões SMB de saída e desabilitar o NTLM pode ajudar a impedir o roubo de credenciais. No entanto, quando as solicitações do SMB falham, o Windows recorre ao WebDAV se estiver habilitado. O roubo de credenciais não pode ser explorado por meio do WebDAV, no entanto, o download do arquivo de som ainda é possível, o que representa a segunda etapa em nossa cadeia de execução remota de código (RCE).
Por que parar agora?
Nesta publicação, detalhamos o processo de pesquisa que levou à descoberta dos dois desvios, incluindo a análise da causa raiz. Como mostramos, o código de análise de caminho do Windows é complexo e, muitas vezes, pode levar a vulnerabilidades. Os pesquisadores de segurança que encontram códigos de manuseio de caminhos são incentivados a pensar na superfície de ataque que ela apresenta.
Além do desvio do MapUrlToZone no contexto do Outlook, não podemos descartar a possibilidade de que essas vulnerabilidades também possam levar a desvios do Mark-of-the-Web (MotW) Desvio de (MotW).
Além da capacidade de vazar credenciais NTLM, também temos a capacidade de baixar e reproduzir um arquivo de som arbitrário. Agora você pode ler a parte 2 desta série do blog,que detalha a vulnerabilidade de análise de som.