
Detector e prova de conceito para uma vulnerabilidade de escrita no page-cache do kernel Linux (CVE-2026-31431) em algif_aead, incluindo um scanner não destrutivo e um exploit local de escalonamento de privilégios.
Este repositório contém o detector e o PoC para a vulnerabilidade de scratch-write no page cache de algif_aead / authencesn do Linux, CVE-2026-31431.
Artigo de divulgação: https://xint.io/blog/copy-fail-linux-distributions
Use apenas em máquinas que você possui ou para as quais tenha autorização explícita. O detector é não destrutivo e opera apenas em arquivos sentinela em diretórios temporários; o PoC e o LPE modificam o estado do page cache em memória, sendo técnicas reais de escalonamento de privilégios locais — executá-los sem autorização geralmente é ilegal.
O algif_aead executa operações AEAD in-place, ou seja, req->src == req->dst. Quando os dados de entrada são enviados via splice() a partir de um arquivo comum, o scatterlist de destino inclui referências às páginas do page cache do arquivo, fazendo com que o kernel possa gravar na cópia do page cache do arquivo.
O authencesn(hmac(sha256),cbc(aes)) realiza um scratch write de 4 bytes no campo seqno_lo do AAD (bytes 4 a 7 do AAD). Combinando o AEAD in-place com o caminho de splice(), um atacante pode fazer com que esses 4 bytes caiam em uma página do page cache de um arquivo legível.
Essa modificação não é gravada de volta no disco; afeta apenas o page cache atual do kernel. Portanto, o conteúdo do arquivo no disco permanece inalterado, mas os leitores que compartilham esse page cache verão o conteúdo adulterado. Arquivos legíveis por todos, como /etc/passwd e /usr/bin/su, podem ser alvos.
Requer toolchain Rust e Cargo instalados na máquina.
Compilar todos os binários Rust:
cargo build --release --bins
Após a compilação, serão gerados:
target/release/cve_2026_31431_detector
target/release/cve_2026_31431_poc
Se o repositório precisar de binários pré-compilados, coloque-os em:
dist/linux-x86_64/cve_2026_31431_detector
dist/linux-x86_64/cve_2026_31431_poc
dist/linux-x86_64/SHA256SUMS
Não envie o diretório target/ inteiro; ele contém artefatos intermediários do Cargo e cache local.
Compilar apenas o detector não destrutivo:
cargo build --release --bin cve_2026_31431_detector
Compilar apenas a versão Rust do poc.py:
cargo build --release --bin cve_2026_31431_poc
Recomenda-se o detector Rust não destrutivo:
./target/release/cve_2026_31431_detector
echo $?
Também é possível executar diretamente via Cargo:
cargo run --release --bin cve_2026_31431_detector
echo $?
Uso do detector Python:
python3 test_cve_2026_31431.py
echo $?
Significado dos códigos de saída:
| Código de saída | Significado |
|---|---|
0 | Nenhuma vulnerabilidade detectada, ou pré-condições não atendidas, por exemplo, AF_ALG / indisponíveis. |
Interpretação comum das saídas:
Operações executadas pelo detector:
AF_ALG e authencesn(hmac(sha256),cbc(aes)) estão disponíveis.sendmsg, definindo o seqno_lo do AAD como o marcador PWND.splice().recv() para acionar a execução do algoritmo.O detector não modifica /usr/bin/su, /etc/passwd ou outros arquivos do sistema. O arquivo sentinela temporário é removido na saída.
Versão Rust do poc.py:
./target/release/cve_2026_31431_poc
ou:
cargo run --release --bin cve_2026_31431_poc
Atenção: este PoC abre /usr/bin/su conforme a lógica do poc.py, polui sua cópia no page cache por meio da primitiva da vulnerabilidade e então executa su. Não faz parte do fluxo de detecção não destrutivo; execute apenas em ambientes de teste autorizados.
python3 exploit_cve_2026_31431.py
python3 exploit_cve_2026_31431.py --shell
Este script localiza o campo UID do usuário atual em /etc/passwd e tenta alterar o UID no page cache para 0000. O /etc/passwd no disco não é modificado, mas os processos do sistema que leem o page cache podem ver o conteúdo adulterado.
Limitações:
1000 a 9999.nscd, sssd e systemd-userdbd, podem mascarar as alterações no page cache de /etc/passwd./etc/passwd precisa permanecer presente entre o patch e a execução de su.Limpando o page cache:
python3 -c "import os; fd=os.open('/etc/passwd', os.O_RDONLY); os.posix_fadvise(fd, 0, 0, os.POSIX_FADV_DONTNEED); os.close(fd)"
Se já tiver obtido um shell root, também é possível executar:
echo 3 > /proc/sys/vm/drop_caches
Reiniciar também limpa o estado do page cache.
Antes do kernel da distribuição ser corrigido, é possível desabilitar o algif_aead:
sudo tee /etc/modprobe.d/disable-algif-aead.conf <<<'install algif_aead /bin/false'
sudo rmmod algif_aead 2>/dev/null
Após aplicar a mitigação, o detector normalmente deve exibir 检测结论:未发现漏洞 e indicar que as pré-condições de disparo não foram atendidas, com código de saída 0.
A correção upstream consiste em restaurar a operação AEAD de in-place para não in-place, evitando que páginas do page cache entrem no scatterlist de destino gravável.
| Arquivo | Descrição |
|---|
test_cve_2026_31431.py | Detector Python não destrutivo. Opera apenas em arquivos sentinela temporários, sem tocar em arquivos do sistema. |
src/main.rs | Detector Rust não destrutivo. Lógica de detecção e códigos de saída idênticos ao detector Python. |
src/bin/poc.rs | Versão Rust do poc.py. Polui o page cache de /usr/bin/su e executa su. |
poc.py | PoC em Python. |
exploit_cve_2026_31431.py | LPE em Python. Tenta obter um shell root poluindo o page cache de /etc/passwd. |
authencesn2 | Detectado como vulnerável ao CVE-2026-31431. |
1 | Erro durante o teste; o resultado não pode ser usado como base para determinar a vulnerabilidade. |
| Saída | Conclusão |
|---|
检测结论:未发现漏洞 | Nenhuma vulnerabilidade detectada, ou pré-condições de disparo não atendidas. |
检测结论:存在 CVE-2026-31431 漏洞 | O marcador PWND caiu com sucesso na página do page cache spliced; a vulnerabilidade está presente. |
检测结论:存在疑似 CVE-2026-31431 漏洞 | O page cache foi modificado; mesmo que o marcador não tenha caído na posição esperada, deve ser considerado afetado. |
测试过程出错,无法判断是否存在漏洞 | Falha na detecção, código de saída 1; é necessário investigar a mensagem de erro e executar novamente. |