
Exploit Rust pour CVE-2026-31431, une primitive d'écriture dans le cache de pages du noyau Linux via AF_ALG splice, permettant une élévation de privilèges vers root grâce à la modification de /etc/passwd ou à l'exécution de shellcode.
Implémentation en Rust de CVE-2026-31431 (Copy Fail) — une primitive d'écriture dans le cache de pages du noyau Linux via splice() avec AF_ALG.
L'implémentation algif_aead du noyau Linux permet à un utilisateur non privilégié d'écrire des données arbitraires dans le cache de pages de n'importe quel fichier lisible via l'appel système splice(). L'algorithme AEAD authencesn écrit seqno_lo (octets 4-7 AAD contrôlés par l'utilisateur) dans le scatterlist de destination à l'offset assoclen + cryptlen, ce qui — lorsqu'il est chaîné aux pages du cache de pages via splice() — aboutit à une écriture arbitraire de 4 octets. Le contenu sur disque reste inchangé, mais tous les lecteurs ultérieurs voient des données corrompues dans le cache de pages.
Noyaux affectés : Linux < 6.12.23, < 6.13.11, < 6.14.2
1. --uid — Bascule le champ UID de l'utilisateur courant à 0000 dans /etc/passwd via une écriture dans le cache de pages. Après la modification, su <nom_utilisateur> avec votre propre mot de passe ouvre un shell root. L'outil tente de vider le cache de pages après l'authentification et avant de lancer le shell, ce qui réduit le risque que SSH continue de voir le compte comme UID 0. Aucune modification du mot de passe root nécessaire. Fonctionne pour tout UID à 4 chiffres (1000-9999).
2. --escalate — Modifie la ligne root dans /etc/passwd via une écriture dans le cache de pages : root:x:0:0:root:... → root::0:0:root :.... Le champ commentaire est complété avec des espaces pour conserver une longueur de ligne identique. Après la modification, su root fonctionne sans mot de passe.
3. --set-password — Élève d'abord les privilèges (supprime le mot de passe root), puis lit le nouveau mot de passe depuis stdin et l'applique avec chpasswd.
4. Mode par défaut (aucune option) — Écrase le cache de pages du binaire su avec des charges utiles shellcode spécifiques à l'architecture (x86_64, x86, aarch64), puis exécute su pour obtenir un shell root.
cargo build
cargo build --release
cargo test
cargo clippy
./copyfail-rs --check
./copyfail-rs --uid
./copyfail-rs --escalate
printf '%s\n' 'mypassword' | ./copyfail-rs --set-password
./copyfail-rs --backup /tmp/su.bak
./copyfail-rs --exec /bin/bash
Les modifications du cache de pages sont volatiles — vider le cache restaure le contenu d'origine sur disque :
echo 3 > /proc/sys/vm/drop_caches
Ce projet est fourni uniquement à des fins de tests de sécurité autorisés et à des fins éducatives.
| Option | Description |
|---|
--check | Pré-vol sécurisé : inspecte la cible su résolue puis quitte |
--escalate | Modifie /etc/passwd dans le cache de pages pour supprimer le mot de passe root, puis su root |
--set-password | Élève d'abord les privilèges, puis lit un nouveau mot de passe root depuis stdin et l'applique via chpasswd |
--uid | Bascule l'UID de l'utilisateur courant à 0 dans /etc/passwd, puis su <nom_utilisateur> |
--backup <chemin> | Sauvegarde le binaire su avant de l'écraser |
--exec <chemin> | Exécute une commande spécifique en tant que root après l'écrasement |
| OS | Noyau | Résultat |
|---|
| Ubuntu 22.04.2 LTS | 6.8.0-87-generic | --escalate réussi, --set-password réussi, --uid réussi |
| Ubuntu 22.04.2 LTS | 6.8.0-107-generic | --escalate réussi, --uid réussi |
| Ubuntu 25.10 | 6.17.0-5-generic | splice EINVAL, noyau corrigé |
| Ubuntu 25.10 | 6.17.0-8-generic | --uid réussi |
| Alpine Linux edge | 6.19.12 | L'exploit s'exécute, écriture dans le cache de pages bloquée par le correctif du noyau |