Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
cve-2026-43687 — Notas de engenharia reversa e um PoC autocontido para a race do cache de acesso do cliente NFS do macOS (CVE-2026-43687), com diff de desmontagem do kext e captura da race via dtrace. | Kitploit
Ferramentas/GitHubGitHub/jvidhan/cve-2026-43687
Forensia de MemóriaAnálise de VulnerabilidadesExploraçãoEngenharia ReversaAnálise de BináriosPapers e PesquisaAprendizado e Educação
GitHubjvidhan/cve-2026-43687

cve-2026-43687

Notas de engenharia reversa e um PoC autocontido para a race do cache de acesso do cliente NFS do macOS (CVE-2026-43687), com diff de desmontagem do kext e captura da race via dtrace.

Ver Repositório
há 9h 32mAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2026-43687 — Notas de engenharia reversa e reprodução

Engenharia reversa independente da corrida (race) no cache de acesso do cliente NFS do macOS (CVE-2026-43687), além de um PoC funcional que dispara a corrida e a captura ao vivo com dtrace.

O bug é uma leitura não sincronizada do ponteiro do cache de acesso do nfsnode em _nfs_vnop_access. Um servidor NFSv3 malicioso pode forçar o cache de acesso a realocar enquanto outra thread o está lendo, produzindo uma divulgação de memória do kernel que um servidor hostil pode influenciar. O macOS 26.7 corrige isso inserindo um lck_rw_t em nfsnode+0x158 e adquirindo-o de forma compartilhada em torno da leitura do cache.


O CVE em resumo

CampoValor
CVECVE-2026-43687
Componentecom.apple.filesystems.nfs (_nfs_vnop_access)
AfetadomacOS Tahoe 26.6 e anteriores, iOS 26.x e anteriores
Corrigido emmacOS Tahoe 26.7, macOS Golden Gate 27, iOS 26.7, iOS 27
Impacto do aviso"Conectar-se a um servidor NFS malicioso pode divulgar memória do kernel."
CVSS v3.16.5 (Médio) — AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
Reportado porR4mbb da KRsecurity e Peter Malone (conforme o aviso da Apple)

Por que este writeup existe

O aviso da Apple para o CVE-2026-43687 documenta o impacto e a versão da correção. Ele não documenta o mecanismo técnico:

  • Qual campo no nfsnode sofre a corrida
  • Onde ocorre a segunda leitura
  • Por que a correção insere um lock naquele offset específico
  • Por que o PoC deve usar access(2) em vez de stat(2)
  • Por que alguns formatos de resposta NFSv3 quebram silenciosamente o mount mesmo quando o formato do protocolo está quase correto

Nenhum writeup técnico público foi encontrado no momento da escrita. Este repositório preenche essa lacuna com uma análise de engenharia reversa independente do kext NFS entre 26.6 e 26.7, e um PoC funcional que reproduz a corrida em um alvo ao vivo.

Isto não é uma reivindicação de descoberta. O CVE foi reportado por R4mbb e Peter Malone e corrigido pela Apple. A contribuição aqui é a análise técnica e a reprodução.


Resumo da vulnerabilidade

_nfs_vnop_access no cliente NFS lê nfsnode+0x158 — o ponteiro para o array de cache de acesso por UID — duas vezes dentro de uma única chamada, sem manter nenhum lock:

root@kitploit:~
; macOS 26.6, com.apple.filesystems.nfs
fffffe000b52def4   ldr  w8,  [x20, #0x160]     ; count
fffffe000b52def8   cmp  w23, w8
fffffe000b52defc   b.ge ...
fffffe000b52df00   ldr  x8,  [x20, #0x158]     ; cache ptr (read #1)
...
fffffe000b52df98   ldr  x8,  [x20, #0x158]     ; cache ptr (read #2)
fffffe000b52dfb0   ldr  w21, [x9]              ; dereference

O escritor, _nfs_nget, realoca o array com kalloc_data e armazena o resultado em +0x158 sempre que o cliente vê um novo UID vindo do servidor:

root@kitploit:~
fffffe000b52100c   bl   0xfffffe000b6a1dd8    ; kalloc
fffffe000b521010   str  x0,  [x22, #0x158]    ; cache ptr
fffffe000b521018   str  w20, [x22, #0x160]    ; cache count

Se outra thread alcançar _nfs_nget no mesmo nfsnode entre as duas cargas do leitor, a segunda carga retorna o novo ponteiro enquanto a primeira leitura — já usada para calcular um offset — baseou-se no antigo. A desreferência subsequente lê do heap do kernel liberado.

A correção do 26.7:

root@kitploit:~
fffffe000b9e3064   str  x0,  [x22, #0x168]    ; cache ptr moved
fffffe000b9e306c   str  w28, [x22, #0x170]    ; cache count moved
fffffe000b9e307c   add  x0,  x22, #0x158      ; lock slot
fffffe000b9e3084   bl   _lck_rw_init          ; init RW lock

e em _nfs_vnop_access:

root@kitploit:~
fffffe000b9f0200   add  x0,  x20, #0x158
fffffe000b9f0204   bl   _lck_rw_lock_shared    ; take the lock
fffffe000b9f0208   ldr  x9,  [x20, #0x168]    ; cache pointer
...
fffffe000b9f0230   bl   _lck_rw_unlock_shared  ; release the lock

Mudança no layout da struct:


O que este repositório contém

Engenharia reversa

  • Diff de disassembly de _nfs_nget e _nfs_vnop_access entre os kexts NFS 26.6 e 26.7 — veja docs/PATCH_DIFF.md
  • Identificação do campo em corrida: nfsnode+0x158 no 26.6
  • Identificação da correção: lck_rw_t inserido em +0x158, ponteiro do cache movido para +0x168, lck_rw_lock_shared adquirido em torno da leitura
  • Análise de syscall: access(2) entra em _nfs_vnop_access; stat(2) passa por _nfs_getattr e nunca alcança a função vulnerável
  • Confirmação em tempo de execução da corrida com dtrace, capturando o ponteiro do cache mudando no meio da chamada

Veja docs/ANALYSIS.md para o writeup completo e docs/ARTIFACTS.md para endereços e amostras de log.

Reprodução

  • poc.sh — um PoC de arquivo único e autocontido:
    1. Para o nfsd da Apple para liberar a porta 2049
    2. Inicia um servidor NFSv3 malicioso em 127.0.0.1 que rotaciona o UID reportado em cada resposta
    3. Monta a exportação em um ponto de montagem novo com noac
    4. Gera um hammer por usuário emitindo access(2) via test -r / test -w
    5. Anexa uma sonda dtrace em nfs_vnop_access, registrando qualquer chamada em que nfsnode+0x158 muda no meio da chamada
    6. Imprime um resumo com a contagem de corridas

O que este PoC demonstra

  • Um servidor NFSv3 malicioso rotacionando o UID que reporta em cada resposta
  • O kernel da vítima realocando o array de cache de acesso em resposta
  • A leitura não sincronizada em _nfs_vnop_access observando o array mudar durante uma única chamada
  • Captura ao vivo desse entrelaçamento via dtrace

O que este PoC NÃO demonstra

  • Um vazamento de memória do kernel em nível de byte visível ao atacante
  • Execução de código, escalação de privilégios ou um shell na vítima

A corrida é a pré-condição para a divulgação. Para transformar a corrida em um vazamento real, um atacante precisaria observar o leitor usando o ponteiro obsoleto e propagar esses bytes para algum lugar que ele possa ler. No arm64e, o valor em nfsnode+0x158 é assinado com PAC e a chave por boot não está disponível a partir do userland, então o dtrace sozinho pode observar a corrida mas não pode decodificar o ponteiro. Veja a seção "Caminhos testados e descartados" em docs/ANALYSIS.md.

O impacto demonstrado é a própria corrida — exatamente a janela que a correção de RW-lock do 26.7 fecha.


Requisitos

Host alvo (vítima)

  • macOS 26.6 ou anterior (kernel vulnerável)
  • dtrace disponível (pode exigir ajuste de SIP em algumas instalações)
  • python3, dscl, mount
  • Root

Nenhum host atacante separado é necessário

O PoC roda inteiramente no alvo. O servidor NFS malicioso se vincula a 127.0.0.1 e o mount é via loopback. Isso mantém o PoC autocontido e reproduzível sem configuração de rede.


Uso

root@kitploit:~
chmod +x poc.sh
sudo ./poc.sh

Ajuste opcional via variáveis de ambiente:

root@kitploit:~
sudo HAMMER_COUNT=30 RUN_SECONDS=600 ./poc.sh

HAMMER_COUNT define o número de threads hammer por usuário (usa quaisquer contas nfsuserNNN existentes, criando-as conforme necessário). RUN_SECONDS define a janela do dtrace.

Saída esperada

root@kitploit:~
[*] ensuring nfsuser accounts exist (UID 201..240)
    nfsuser accounts available: 12
[*] starting evil NFS server on 127.0.0.1:2049
[*] mounting /Users/Shared/nfs_test (with noac)
    mount check: hello.txt statable
[*] spawning up to 12 per-user threads + 1 root loop
    started 12 user threads + 1 root loop
[*] running dtrace for 180s — looking for RACE lines
[*] stopping dtrace
[*] cleaning up

=================== SUMMARY ===================
RACE events caught: 16

Vulnerable interleaving observed — sample:
RACE nd=fffffe5f53cbb940 in=(0,0) out=(b0967e0023297878,0)
RACE nd=fffffe5f534db940 in=(0,0) out=(84dd7e0023297878,0)
RACE nd=fffffe5f53cbb940 in=(0,0) out=(c9a37e0023297878,0)
RACE nd=fffffe5f538ab940 in=(0,0) out=(1867e0023297878,0)
RACE nd=fffffe5f539db940 in=(0,0) out=(149bfe0023297878,0)

CVE-2026-43687 trigger SUCCESSFUL
===============================================

Cada linha RACE é uma chamada de nfs_vnop_access em que o ponteiro do cache de acesso mudou no meio da chamada.

Verificação da correção

Em um sistema corrigido (26.7 / 27), a mesma carga de trabalho produz zero eventos RACE. Veja docs/PATCH_DIFF.md para a comparação de disassembly.


Armadilhas do servidor NFSv3 (para reprodutibilidade)

Dois bugs no servidor do PoC foram corrigidos durante o desenvolvimento e estão documentados aqui para que outros construindo ferramentas semelhantes não os encontrem:

  1. ACCESS3resok requer post_op_attr, não fattr3. A RFC 1813 define a resposta como post_op_attr obj_attributes; uint32 access;. post_op_attr inclui um prefixo bool antes do fattr3. Omitir esse bool faz a resposta ficar 4 bytes menor; o cliente a rejeita silenciosamente e o mount nunca se torna utilizável.

  2. LOOKUP para nomes AppleDouble (._*) deve retornar NFS3ERR_NOENT (2), não NFS3ERR_STALE (70). O macOS sonda por sidecars ._<name> durante a resolução normal de caminho. Retornar STALE envenena o mount.

Ambos estão documentados em docs/ANALYSIS.md.


Uma nota sobre o valor em tempo de execução

Os valores out na saída do RACE têm um padrão constante nos 48 bits inferiores (...7e0023297878) entre diferentes nfsnodes, variando apenas nos 16 bits superiores. Isso confirma que o campo é assinado com PAC ou ofuscado, não um ponteiro de kernel bruto. Você pode observar a transição de estado (NULL → populado) a partir do userland, mas não pode decodificar ou desreferenciar o ponteiro sem a chave PAC por boot do kernel.

Pela mesma razão, a simbolização contra o KDK não é útil para esses valores — eles não são endereços relativos a texto.


Créditos

  • Descoberta original: R4mbb da KRsecurity e Peter Malone, conforme o aviso de segurança da Apple para o CVE-2026-43687.
  • Análise independente e PoC: jvidhan
  • Referência: O aviso da Apple e o binário corrigido serviram como linha de base para comparação com a versão vulnerável. O KDK para macOS 26.6 (build 25G72) forneceu símbolos para a análise do lado do kernel.

Isenção de responsabilidade

Este repositório é fornecido para pesquisa e educação em segurança defensiva apenas.

  • Destina-se ao uso contra sistemas que você possui ou tem permissão escrita explícita para testar.
  • Usar esta ferramenta contra sistemas que você não possui ou controla pode violar leis locais, nacionais ou internacionais.
  • O(s) autor(es) não assumem nenhuma responsabilidade por qualquer uso indevido ou dano causado por este código.
  • O PoC é limitado a demonstrar uma corrida no kernel. Ele não alcança execução de código, escalação de privilégios ou um vazamento de memória em nível de byte. Quaisquer alegações de RCE ou divulgação completa de memória a partir deste PoC não são sustentadas pela análise incluída.
  • Apple, macOS, XNU, NFS, autofs e automountd são marcas registradas da Apple Inc. Este projeto não é afiliado nem endossado pela Apple.

Licença

MIT. Veja LICENSE.

Baixar ferramenta
OffsetmacOS 26.6macOS 26.7
+0x158ponteiro do array de cachelck_rw_t
+0x160contagem do cache(parte do lock)
+0x168(outro)ponteiro do array de cache
+0x170(outro)contagem do cache