
Regras de detecção, assinaturas YARA, regras auditd/Wazuh e modelos de evento MISP para a vulnerabilidade LPE do kernel Linux CVE-2026-31431 (Copy Fail). Inclui IoCs, etapas de mitigação e análise de exploração.
Publicado: 2026-04-30
CVSSv3: 7.8 (Alto)
Tipo: Escalação Local de Privilégios (LPE)
Subsistema: kernel Linux algif_aead / template criptográfico authencesn
Atingido: kernels Linux 4.14 – 6.18.21 (praticamente todas as distribuições desde 2017)
Referências:
A CVE-2026-31431 é uma falha lógica introduzida no kernel 4.14 (2017) na interseção de três alterações independentes:
authencesn (adicionado em 2011 para suporte a IPsec ESN) escreve 4 bytes de dados temporários além do limite do buffer de saída.AF_ALG ganhou suporte AEAD em 2015, permitindo que o espaço do usuário envie dados via splice() de arquivos armazenados em cache de página.algif_aead.c foi otimizado para operar in-place (req->src == req->dst), colocando páginas ativas do cache de página em uma lista de dispersão gravável.O resultado: um usuário não privilegiado pode escrever exatamente 4 bytes controlados pelo atacante na cópia do cache de página do kernel de qualquer arquivo legível — incluindo binários setuid e /etc/passwd — sem tocar no arquivo em disco. O PoC funcional é um script Python de 732 bytes. Nenhuma condição de corrida. Nenhum deslocamento por distribuição. Confiável em Ubuntu, RHEL, Amazon Linux e SUSE.
Attacker opens AF_ALG socket (family 38, type 5) └─ Binds to "authencesn(hmac(sha256),cbc(aes))" └─ Sets SOL_ALG (279) options including key and authsize └─ Accepts a connection socket
Attacker opens target file (e.g., /etc/passwd) read-only └─ Uses splice() to feed page-cache pages into the AEAD socket's RX buffer └─ Sends crafted AAD via sendmsg() — bytes 4–7 of AAD = attacker-controlled write value
authencesn performs in-place decryption: └─ scatterwalk_map_and_copy writes seqno_lo into the chained page-cache page └─ recvmsg() returns an error (HMAC fails — expected), but the write already happened
Page-cache now contains attacker-modified copy of the file └─ Kernel executes from page-cache, not disk └─ On-disk file is UNCHANGED — file integrity tools see nothing
O PoC tem como alvo `/etc/passwd`: ele encontra o offset do campo UID do usuário em execução e o sobrescreve com `0000`, em seguida invoca `su` para obter um shell root.
---
## Limitações de Detecção
> **Leia esta seção antes de implantar quaisquer regras abaixo.**
Este exploit tem duas propriedades que limitam significativamente a cobertura de detecção:
**1. A gravação vai para o cache de página, não para o sistema de arquivos.**
Qualquer ferramenta de detecção que monitore eventos do sistema de arquivos — `inotify`, `fanotify`, AIDE, Tripwire, auditd path watches — **não** observará a modificação. O arquivo em disco nunca é escrito. Isso significa que os flags `-p w` (write) nas watches de caminho do auditd para `/usr/bin/su` ou `/etc/passwd` não capturarão a gravação real da exploração.
**2. O mecanismo usa interfaces legítimas do kernel.**
Soquetes `AF_ALG`, `splice()` e `authencesn` têm usos legítimos (IPsec, auto-testes do kernel, E/S estilo sendfile). A detecção deve focar na *combinação* dessas primitivas em vez de qualquer uma isoladamente, e falsos positivos devem ser esperados em sistemas executando IPsec ou realizando testes criptográficos do kernel.
**O que a detecção PODE capturar:**
- A chamada de sistema `socket(AF_ALG, SOCK_SEQPACKET, 0)`
- A chamada de sistema `splice()` correlacionada com a acima, especialmente perto do acesso a binários setuid
- O próprio script PoC (via YARA)
- A string de algoritmo específica `authencesn(hmac(sha256),cbc(aes))` na memória do processo ou arquivos de script
**O que a detecção NÃO PODE capturar:**
- A gravação real no cache de página (em memória, sem evento de sistema de arquivos)
- Uso pós-exploração da entrada modificada do cache de página (parece uma chamada normal de `su` ou `passwd`)
- Variantes que evitam Python ou a string de algoritmo específica
---
## Mitigação Imediata
Antes de implantar regras de detecção, aplique esta mitigação em qualquer host não corrigido:```bash
# Disable algif_aead kernel module — blocks the exploit primitive entirely
echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/disable-algif-aead.conf
sudo rmmod algif_aead 2>/dev/null || true
Verifique se a mitigação está ativa usando o detector oficial:```bash
python3 test_cve_2026_31431.py
> **Nota:** O comando `rmmod` falhará se o módulo não estiver carregado no momento; isso é aceitável. A configuração `modprobe.d` impede carregamentos futuros. Essa mitigação não tem impacto em cargas de trabalho padrão de TLS, SSH ou criptografia de sistema de arquivos — afeta apenas IPsec com Números de Sequência Estendidos usando o template `authencesn`, que é incomum fora de gateways de VPN dedicados.
---
## Regra YARA
Salve como `cve_2026_31431.yar`
> **Escopo de varredura:** Esta regra foi projetada para escanear arquivos de script Python em disco ou extraídos de dumps de memória. Ela corresponderá ao PoC conhecido e variantes próximas. Ela NÃO detectará a atividade de exploração no nível de syscall — use as regras do auditd/Wazuh para isso.```yara
rule CVE_2026_31431_CopyFail_PoC_HighConfidence {
meta:
description = "High-confidence match: CVE-2026-31431 Copy Fail PoC or close variant"
author = "Detection Engineering"
reference = "https://xint.io/blog/copy-fail-linux-distributions"
cve = "CVE-2026-31431"
date = "2026-04-30"
severity = "High"
cvss = "7.8"
strings:
// Algorithm string unique to this exploit path — very high fidelity
$alg_full = "authencesn(hmac(sha256),cbc(aes))" ascii
// Specific socket call signature from PoC: AF_ALG=38, SOCK_SEQPACKET=5
$socket_call = "socket(38,5,0)" ascii
// SOL_ALG socket option (decimal 279)
$solalg = "setsockopt(279" ascii
// Hex key/iv payload written via setsockopt in PoC
$key_payload = "0800010000000010" ascii
// splice() usage in context of AEAD operations
$splice = "splice(" ascii
// Target indicators from PoC (page-cache corruption targets)
$target_passwd = "/etc/passwd" ascii
$target_su = "/usr/bin/su" ascii
// AF_ALG aead bind strings
$aead_bind = "\"aead\"" ascii