CVE-2026-31431 (Copy Fail): como a Appbox mitigou o problema
Uma falha séria no kernel Linux, CVE-2026-31431, foi divulgada na semana passada. Veja como a Appbox mitigou o problema e implantou a correção do kernel Debian.
CVE-2026-31431 (Copy Fail) - como mitigamos o problema
Na semana passada foi divulgada uma séria escalada local de privilégios no kernel Linux: CVE-2026-31431, apelidada de "Copy Fail". Ela afeta uma ampla variedade de versões de kernel em distribuições Linux modernas, e um exploit público apareceu rapidamente após a divulgação.
Quero explicar de forma direta o que aconteceu, o que isso significa para a Appbox e o que fizemos a respeito. Versão curta: graças à forma como nossos containers são construídos, apps rodando com remapeamento de user namespace já estavam protegidos contra a transformação disso em root do host mesmo antes dos kernels corrigidos serem implantados. Ontem (4 de maio de 2026), também realizamos manutenção emergencial para atualizar todos os servidores para um kernel corrigido, então o bug agora foi totalmente removido da nossa frota.
O que é o "Copy Fail"?
A CVE-2026-31431 é uma falha na API criptográfica AF_ALG do kernel. Ao fazer bind a uma cifra específica (authencesn(hmac(sha256),cbc(aes))) e abusar da forma como o kernel faz splice de páginas para um buffer temporário, um usuário local sem privilégios consegue gravar blocos arbitrários de 4 bytes diretamente no page cache de arquivos que não deveria ter permissão para modificar, incluindo binários SUID como /usr/bin/su.
Depois que a cópia em cache de su é sobrescrita por um pequeno ELF malicioso, a próxima execução roda o código do atacante como UID 0. Fim de jogo para o host.
Para os detalhes técnicos mais profundos (disassembly de shellcode, traces de syscalls e tudo mais), o writeup do Andrea Veri é excelente: CVE-2026-31431: Copy Fail vs. rootless containers. Ele também demonstrou, com eBPF e provas de uid_map, exatamente o que vamos explicar a seguir: user namespaces neutralizam este exploit.
Por que os apps da Appbox já estavam mitigados
O exploit depende de setuid(0) realmente conceder root do host. Em um container rodando com user namespaces habilitados, não é isso que acontece.
User namespaces mapeiam o espaço de UIDs do container para uma faixa diferente e sem privilégios no host. Então, quando o exploit tem sucesso dentro do container e setuid(0) retorna sucesso, o shell "root" resultante é mapeado para um usuário comum sem privilégios no host, não root real. O shellcode roda, o prompt muda para #, mas no host:
podman 27943 0.0 0.0 2984 2028 pts/1 S+ 22:15 0:00 sleep 100É isso. Sem acesso a arquivos do host, sem /etc/shadow, sem root do host. A fronteira de namespace do container impede que isso vire uma fuga para root no host.
No nível da plataforma, cada Appbox recebe seu próprio daemon Docker iniciado com remapeamento de user namespace habilitado. Em pseudocódigo, fica mais ou menos assim:
start_docker_daemon(
userns_remap = appbox_id,
container_namespace = appbox_id
)Esse mapeamento é apoiado por uma faixa subordinada dedicada de UID/GID no host:
write "/etc/subuid" -> "<appbox-id>:<host-subuid-start>:65536"
write "/etc/subgid" -> "<appbox-id>:<host-subgid-start>:65536"Além disso, definições de apps ainda podem sobrescrever explicitamente UsernsMode quando um app precisa de tratamento especial:
container_config = {
userns_mode: app.userns_mode,
network_mode: app.network_mode,
...
}Então a forma precisa de descrever é: o remapeamento de user namespace faz parte do padrão da plataforma, e exceções por app são explícitas. Há um pequeno número de apps que precisam de configurações diferentes porque expõem funcionalidades que exigem capacidades adicionais, e esses casos são tratados separadamente.
Em outras palavras: para apps rodando com a configuração remapeada normal, o Copy Fail não conseguia transformar um comprometimento de container em root do host.
O que ainda queríamos corrigir
User namespaces impedem a fuga para o host, mas não fazem o bug desaparecer dentro do container. Um atacante ainda poderia escalar para "root do container" dentro da fronteira do app, o que, embora contido, ainda não é aceitável. O próprio kernel estava vulnerável, e queríamos remover isso.
Assim que soubemos do bug, começamos imediatamente a avaliar nossa exposição. Mesmo que o remapeamento de user namespace já bloqueasse a parte de fuga para o host no nosso setup normal de apps, ainda queríamos eliminar o bug subjacente do kernel o mais rápido possível.
O que fizemos ontem
No domingo à noite, agendamos manutenção emergencial para segunda-feira, 4 de maio de 2026, a janela mais cedo em que poderíamos implantar uma atualização de kernel em toda a frota.
Durante a janela:
- Todos os hosts foram atualizados usando os pacotes oficiais de kernel do Debian que contêm a correção do "Copy Fail".
- O objetivo era simples: remover totalmente o caminho vulnerável do kernel, não apenas depender do nosso isolamento por namespace existente.
A manutenção foi concluída. Todos os hosts Appbox agora rodam um kernel corrigido.
O que isso significa para você
- Você não precisava fazer nada. Seus apps continuaram rodando, e quaisquer breves oscilações durante a janela de manutenção foram o único efeito visível para clientes.
- Mesmo antes da correção de ontem, o remapeamento de user namespace significava que este bug não poderia transformar o comprometimento de um app normal em root do host. Esse é exatamente o tipo de cenário para o qual esse modelo de isolamento existe.
- Daqui para frente, nossa política continua a mesma: user namespaces permanecem ativados por padrão, e as pouquíssimas exceções passam por revisão de segurança adicional.
O quadro maior
Esta é uma daquelas CVEs em que a manchete ("escalada local de privilégios, exploit público, todo kernel moderno afetado") soa catastrófica, e para muitos ambientes multi-tenant ela realmente foi. O motivo de não ter sido catastrófica para nós é o mesmo motivo pelo qual tomamos decisões arquiteturais anos atrás que, às vezes, custam um pouco de compatibilidade: rodamos apps com o princípio do menor privilégio embutido na camada de containers, não remendado depois.
Defesa em profundidade realmente funciona. Bug na camada do kernel? A camada de namespace segurou. Bug na camada de namespace? Redução de capabilities e seccomp capturam boa parte do resto. Não fingimos que uma única camada é perfeita; apenas garantimos que sempre exista uma próxima.
Se tiver qualquer dúvida sobre isso ou sobre como seus apps específicos estão configurados, entre em contato.
Tem dúvidas? Entre em contato em support@appbox.co ou abra um ticket em billing.appbox.co.
