Precisa de computação em nuvem? Comece agora mesmo

Chamada e registro — ataque de retransmissão ao cliente WinReg RPC

Stiv Kupchik

escrito por

Stiv Kupchik

October 19, 2024

Stiv Kupchik

escrito por

Stiv Kupchik

Stiv Kupchik é um pesquisador de segurança sênior de Tel Aviv, Israel.

Stiv Kupchik, pesquisador da Akamai, encontrou uma nova vulnerabilidade de elevação de privilégio (EoP) no cliente de registro remoto da Microsoft.
Stiv Kupchik, pesquisador da Akamai, encontrou uma nova vulnerabilidade de elevação de privilégio (EoP) no cliente de registro remoto da Microsoft.

Resumo executivo

  • Stiv Kupchik, pesquisador da Akamai, encontrou uma nova vulnerabilidade de elevação de privilégio (EoP) no cliente de registro remoto da Microsoft, CVE-2024-43532, com uma pontuação CVSS de 8,8.

  • A vulnerabilidade explora um mecanismo de fallback na implementação do cliente WinReg que usa protocolos de transporte obsoletos de forma desprotegida quando o transporte SMB está indisponível.

  • Ao explorar essa vulnerabilidade, um invasor pode retransmitir os detalhes de autenticação NTLM do cliente para os Serviços de Certificados do Active Directory (ADCS) e solicitar um certificado de usuário para utilizar em outras autenticações no domínio. Fornecemos uma prova de conceito em nosso repositório do GitHub.

  • A vulnerabilidade foi divulgada de forma responsável ao Microsoft Security Resource Center em fevereiro de 2024 e corrigida como parte da Patch Tuesday de outubro de 2024.

  • A vulnerabilidade afeta todas as versões sem correção do Windows.

  • Nossas descobertas também foram apresentadas na conferência de segurança de computadores No Hat.

Introdução

MS-RPC é a implementação da Microsoft do protocolo e padrão RPC (Chamada de procedimento remoto). RPC é uma forma de mecanismo de comunicação entre processos que permite que os processos exponham funcionalidades que podem ser chamadas por outros processos. Ele é um componente essencial do sistema operacional Windows e vários serviços dependem dele, desde o gerenciador de serviços até os desligamentos no wininit.

Nossa equipe fez muitas pesquisas sobre o MS-RPC, tanto pesquisas ofensivas, nas quais descobrimos um grande vetor de ataque na forma de ataques de cache, quanto pesquisas defensivas, nas quais analisamos mecanismos de segurança para ele.

Desta vez, queríamos analisar o RPC de uma perspectiva diferente. Qualquer protocolo que permita a comunicação e as operações entre computadores diferentes precisa estar envolvido com a autenticação do usuário e, de fato, o protocolo RPC oferece suporte à passagem de credenciais e à autenticação como parte de seu processo de vinculação. No entanto, onde há autenticação, há potencialidade de retransmissão de autenticação, por isso nos propusemos a encontrar oportunidades de retransmissão.

RPC, autenticação e aspectos intermediários

As sessões de RPC são operadas através de vínculos. Um aplicativo cliente se conecta a um aplicativo servidor, vincula-se à interface RPC necessária e solicita a execução de uma função específica (Figura 1).

Um aplicativo cliente se conecta a um aplicativo servidor, vincula-se à interface RPC necessária e solicita a execução de uma função específica (Figura 1). Fig. 1: O processo básico de chamada RPC

A solicitação e a resposta do vínculo podem transportar vários campos de dados, conforme necessário para a conexão. Normalmente, se não houver autenticação envolvida, a vinculação RPC será usada simplesmente para decidir sobre a sintaxe de transferência que será usada para encapsular parâmetros de função em chamadas subsequentes.

O que falta nessa interação? Autenticação, é claro! Como o servidor pode saber a identidade do cliente e se esse cliente tem permissão para executar a ação solicitada? A resposta é: isso não acontece, a menos que o cliente tenha adicionado especificamente o contexto de segurança (autenticação) ao vínculo. Por padrão, todas as conexões RPC não são autenticadas, e nem todos os servidores RPC exigem autenticação.

Para autenticar (ou, em termos de RPC, "adicionar contexto de segurança"), o cliente precisa acrescentar outros dados à solicitação de vinculação, negociar o protocolo de autenticação (por exemplo, NTLM ou Kerberos) e inserir metadados adicionais exigidos pelo protocolo de autenticação (como nome de usuário, domínio e outros; Figura 2).

Para autenticar (ou, em termos de RPC, "adicionar contexto de segurança"), o cliente precisa acrescentar outros dados à solicitação de vinculação, negociar o protocolo de autenticação (por exemplo, NTLM ou Kerberos) e inserir metadados adicionais exigidos pelo protocolo de autenticação (como nome de usuário, domínio e outros; Figura 2). Fig 2: Metadados de autenticação adicionados à solicitação de vinculação de RPC

Encontrar alvos de pesquisa

A primeira ordem do dia é entender como deve ser a autenticação do ponto de vista de API. Isso é feito por meio de uma chamada a uma das funções RpcBindingSetAuthInfo* do cliente após a criação de um identificador de vínculo. Se você analisar a documentação dessas funções, notará um campo chamado AuthenticationLevel; ele indica o nível de segurança que a autenticação oferece.

A segurança com autenticação é mais do que apenas verificar se o usuário existe e está autorizado: ela também pode ser usada para evitar adulterações. Os níveis de autenticação variam desde uma simples verificação de que a conexão foi bem-sucedida (RPC_C_AUTHN_LEVEL_CONNECT) até a criptografia e assinatura completas de todo o tráfego para garantir que nada seja adulterado (RPC_C_AUTHN_LEVEL_PKT_PRIVACY). É claro que os invasores se interessam pelo primeiro nível: sem defesas no tráfego, ele pode ser adulterado.

Mas a história não é tão simples. Os ataques de retransmissão de RPC não são um conceito novo, portanto, muitos dos clientes e servidores de RPC no Windows já foram corrigidos para usar o nível mais alto de autenticação e garantir que os ataques de retransmissão não sejam bem-sucedidos. Precisaremos vasculhar o sistema operacional na esperança de encontrar algumas porções de código mais antigas que ainda estejam desprotegidas por algum motivo (Figura 3).

Precisaremos vasculhar o sistema operacional na esperança de encontrar algumas porções de código mais antigas que ainda estejam desprotegidas por algum motivo (Figura 3). Fig. 3: Execução de um script IDAPython na pasta system32 de um servidor Windows para encontrar instâncias de autenticação desprotegida de RPC; o script pode ser encontrado em nosso repositório do GitHub

WinReg — um candidato promissor

Como era de se esperar, a lista de alvos potenciais que encontramos incluía menos de 5% do total de servidores e clientes RPC; a maioria simplesmente não usa mais autenticação desprotegida. Mas encontramos um candidato promissor em advapi32.dll.

advapi32.dll é um componente central da API do Windows e implementa grande parte da lógica "avançada" do Windows (como o próprio nome sugere). Ele exporta mais de 800 funções de vários campos: registro de eventos, criptografia, WMI e mais.

Para nossos objetivos, descobrimos que, em algumas ocasiões, a função interna BaseBindToMachine chama RpcBindingSetAuthInfoA com um nível de autenticação de RPC_C_AUTHN_LEVEL_CONNECT, que é o que queremos. BaseBindToMachine é chamada pela função exportada (embora não documentada) RegConnectRegistryExW (Figura 4), se receber um caminho UNC para um nome de computador.

BaseBindToMachine é chamada pela função exportada (embora não documentada) RegConnectRegistryExW (Figura 4), se receber um caminho UNC para um nome de computador. Fig. 4: A documentação do Rust para RegConnectRegistryExW, pois não está documentada no MSDN

Ao analisar a BaseBindToMachine, vemos que, na verdade, ela contém chamadas para RpcBindingSetAuthInfoW e RpcBindingSetAuthInfoA. O primeiro é usado com segurança, com o nível de autenticação RPC_C_AUTHN_LEVEL_PKT_PRIVACY, enquanto o segundo usa o nível de autenticação RPC_C_AUTHN_LEVEL_CONNECT, que pode ser retransmitido, pois não verifica a autenticidade nem a integridade da conexão (Figura 5).

O primeiro é usado com segurança, com o nível de autenticação RPC_C_AUTHN_LEVEL_PKT_PRIVACY, enquanto o segundo usa o nível de autenticação RPC_C_AUTHN_LEVEL_CONNECT, que pode ser retransmitido, pois não verifica a autenticidade nem a integridade da conexão (Figura 5). Fig. 5: As duas chamadas para definir as informações de autenticação

Só precisamos descobrir por que há duas chamadas conflitantes. Ao analisar a lógica da função, vemos que ela tem uma variável de ponteiro de função e uma matriz de funções (Figura 6). Essas funções definem as informações de vinculação RPC para usar um transporte RPC específico; por padrão, ele tenta usar SMB e pipes nomeados, mas, se falha, ele tenta se vincular por SPX, TCP/IP e outros.

Por algum motivo, quando ele volta a usar qualquer outro protocolo além do SMB, ele usa o RpcBindingSetAuthInfoA para definir o nível de autenticação como Connect, que não é protegido.

Só precisamos descobrir por que há duas chamadas conflitantes. Ao analisar a lógica da função, vemos que ela tem uma variável de ponteiro de função e uma matriz de funções (Figura 6). Fig. 6: Ponteiros de função e a matriz de funções dentro da BaseBindToMachine

O fallback para TCP/IP é bastante promissor, pois significa que podemos usar o método de autenticação desprotegido para retransmitir o tráfego usando um ataque machine-in-the-middle sem que o cliente perceba. Embora isso também seja possível com os outros protocolos de transporte, eles são bastante obsoletos, portanto, pode não ser realista encontrá-los em uma rede moderna (e usá-los pode gerar algumas preocupações). O TCP/IP é muito mais comum como transporte RPC, portanto, não deve haver problema, mesmo em uma configuração de equipe vermelha.

É importante saber que tanto BaseBindToMachine como RegConnectRegistryExW aceitam um sinalizador como argumento que impede o comportamento de fallback, mas a função básica RegConnectRegistryW chama RegConnectRegistryExW sem a presença desse sinalizador.

O processo de retransmissão

A retransmissão é bastante simples, pois a retransmissão NTLM é uma técnica comum. A maior parte da lógica de que precisamos já está implementada no ntlmrelayx do Impacket, que é o que mais usaremos.

Criação do servidor de retransmissão RPC

O que falta ao ntlmrelayx é um servidor TCP/IP RPC, pois ele implementou apenas um servidor SMB. Dessa forma, precisaremos criar nosso próprio servidor de retransmissão, que rejeita o pipe winreg nomeado para acionar um fallback para a função de vinculação TCP/IP.

Há três pontos críticos que precisamos implementar:

  1. O mapeador de pontos de extremidade RPC

  2. A solicitação de vinculação RPC com NTLM

  3. O desafio NTLM

O mapeador de pontos de extremidade RPC é responsável por traduzir os UUIDs da interface RPC em seus respectivos pontos de extremidade, que, no caso do transporte TCP/IP, seria um número de porta. Ao contrário do SMB, em que os pontos de extremidade são pipes nomeados que são exclusivos e podem ser conhecidos antecipadamente, os pontos de extremidade TCP usam portas efêmeras, sendo necessária outra camada de tradução.

A parte crítica são os problemas relacionados ao NTLM. A forma como a vinculação RPC funciona com NTLM é que uma mensagem de negociação NTLM é enviada durante a solicitação de vinculação, e um desafio NTLM é enviado com a resposta de vinculação. Por fim, o cliente precisa enviar outra mensagem, chamada AUTH3, com a resposta do desafio (Figura 7).

O cliente precisa enviar outra mensagem, chamada AUTH3, com a resposta do desafio (Figura 7). Fig. 7: Autenticação NTLM por meio de vinculação RPC

Basta analisar as mensagens correspondentes em nosso servidor RPC para retransmitir. Quando vemos uma mensagem de negociação NTLM em uma mensagem de associação, abrimos nossa própria conexão com o servidor de autenticação de destino e também solicitamos a autenticação via NTLM. Depois, basta capturar o desafio que o servidor nos envia, retransmiti-lo à vítima e retransmitir a resposta de volta ao servidor para obter nossa própria sessão autenticada.

Tudo que precisamos considerar é para qual servidor queremos retransmitir a autenticação.

Retransmissão de RPC para RPC

A ideia imediata seria fazer a retransmissão para outro servidor RPC em um computador diferente, como o gerenciador de serviços ou o agendador de tarefas, e obter uma execução remota de código dessa forma. O problema com isso, no entanto, é  que ninguém mais usa autenticação desprotegida via RPC, então não podemos retransmitir para nenhum servidor RPC de alto perfil. (Essa falta de autenticação desprotegida via RPC é o mesmo motivo pelo qual tínhamos alvos de pesquisa limitados.)

Os servidores RPC do gerenciador de serviços e do agendador de tarefas exigem RPC_C_AUTHN_LEVEL_PKT_PRIVACY, que criptografa todo o tráfego com o hash NTLMv2 do cliente, que não conhecemos nem mesmo com a retransmissão. Em vez disso, temos que olhar por um ângulo diferente.

De RPC para ADCS

Felizmente, o pessoal da SpecterOps trabalhou muito no ADCS, especificamente na retransmissão de NTLM para o ADCS. Isso também está implementado no Impacket por padrão, portanto, tudo que precisamos fazer é passar nossa sessão autenticada para o módulo HTTPAtack do Impacket e deixar a mágica acontecer.

O servidor da Web HTTP do ADCS não exige nenhuma segurança e é vulnerável a ataques de retransmissão. Ao explorar isso, depois de nos autenticarmos nele, podemos solicitar um certificado de usuário, que pode ser usado por si só para autenticar, sem termos que passar pelo problema de retransmitir a autenticação novamente (Figura 8).

Ao explorar isso, depois de nos autenticarmos nele, podemos solicitar um certificado de usuário, que pode ser usado por si só para autenticar, sem termos que passar pelo problema de retransmitir a autenticação novamente (Figura 8). Fig 8: Solicitação e recebimento de um certificado do ADCS após um ataque de retransmissão NTLM

Usamos esse certificado para autenticar o serviço LDAP no controlador de domínio e criar um novo administrador de domínio persistente no domínio comprometido (Figura 9).

Usamos esse certificado para autenticar o serviço LDAP no controlador de domínio e criar um novo administrador de domínio persistente no domínio comprometido (Figura 9). Fig 9: Criação de um novo administrador de domínio usando um shell LDAP

Possível impacto

Uma função no advapi não é interessante por si só; ela só tem impacto se outra coisa a estiver usando. Uma rápida pesquisa de importações de RegConnectRegistryExW ou RegConnectRegistryExA não mostra nada em um controlador de domínio atualizado, mas uma pesquisa por RegConnectRegistryW revela muitos candidatos em potencial, como certutil e certsrv (AD CS), EFS, DFS e outros.

Detecção

O serviço de registro remoto não está ativado por padrão em todos os computadores Windows. É possível detectar seu status usando o seguinte osquery:

  SELECT display_name, status, start_type, pid FROM services WHERE name='RemoteRegistry'

Isso, no entanto, não protege contra o CVE-2024-43532, pois é um problema de cliente. Os resultados da consulta devem gerar casos de uso reais do registro remoto na organização que talvez seja necessário levar em conta ao fortalecer seus sistemas.

Você pode usar a seguinte regra YARA para detectar clientes que usam qualquer uma das WinAPI vulneráveis:

  import "pe"

rule winreg_client_import {
    meta:
        description =  "Detect binaries that rely on RegConnectRegistry"
        author = "Stiv Kupchik with Akamai Technologies"

    condition:
        pe.is_pe and (
            pe.imports(pe.IMPORT_ANY, "advapi32.dll", "RegConnectRegistryA")
            or pe.imports(pe.IMPORT_ANY, "advapi32.dll", "RegConnectRegistryW")
            or pe.imports(pe.IMPORT_ANY, "advapi32.dll", "RegConnectRegistryExA")
            or pe.imports(pe.IMPORT_ANY, "advapi32.dll", "RegConnectRegistryExW")
        )
    
}

Os usuários da Akamai Guardicore Segmentation também podem criar regras de política para o tráfego que chega ao serviço RemoteRegistry (Figura 10).

Os usuários da Akamai Guardicore Segmentation também podem criar regras de política para o tráfego que chega ao serviço RemoteRegistry (Figura 10). Fig. 10: Regra da política de segmentação para alertar sobre o tráfego para o serviço RemoteRegistry

Também é possível usar o ETW (Event Tracing for Windows) para monitorar o tráfego RPC nos lados cliente e servidor da comunicação. Discorremos sobre esse tópico em nossa apresentação na Black Hat 2023 e na postagem no blog relacionada. Os usuários podem usar nossa ferramenta de código aberto de visibilidade de RPC para rastrear chamadas de RPC e filtrar o UUID {338cd001-2244-31f1-aaaa-900038001003} da interface de RPC WinReg.

Conclusão

Embora o protocolo RPC e o MS-RPC tenham sido criados com a segurança em mente, podemos ver claramente a evolução dos princípios de segurança ao longo do tempo analisando várias implementações na interface RPC. Embora a maioria dos servidores e clientes de RPC seja segura atualmente, é possível, periodicamente, descobrir vestígios de implementações desprotegidas em graus variados.

Nesse caso, conseguimos realizar a retransmissão NTLM, que é uma classe de ataques que pertence ao passado. Isso só prova que as defesas de rede devem ser tão completas quanto possível, pois nunca se sabe qual interface antiga ainda está exposta ou em execução.

Cronograma de divulgação

01/02/2024 — Vulnerabilidade divulgada ao MSRC

25/04/2024 — Relatório fechado como problema de documentação

17/06/2024 — Relatório reaberto com melhor PoC e explicação

08/07/2024 — Vulnerabilidade confirmada

08/10/2024 — Vulnerabilidade corrigida

19/10/2024 — Postagem no blog publicada



Stiv Kupchik

escrito por

Stiv Kupchik

October 19, 2024

Stiv Kupchik

escrito por

Stiv Kupchik

Stiv Kupchik é um pesquisador de segurança sênior de Tel Aviv, Israel.