
Détecteur et preuve de concept pour une vulnérabilité d'écriture dans le cache de pages du noyau Linux (CVE-2026-31431) dans algif_aead, incluant un scanner non destructif et un exploit d'élévation de privilèges locale.
Ce dépôt contient le détecteur et le PoC pour la vulnérabilité de scratch-write dans le cache de pages Linux algif_aead / authencesn CVE-2026-31431.
Article de divulgation : https://xint.io/blog/copy-fail-linux-distributions
À utiliser uniquement sur des machines que vous possédez ou pour lesquelles vous disposez d'une autorisation explicite. Le détecteur est non destructif et ne manipule que des fichiers sentinelles dans un répertoire temporaire ; le PoC et le LPE modifient l'état du cache de pages en mémoire, ce qui constitue une véritable technique d'élévation de privilèges locale, et son exécution sans autorisation est généralement illégale.
algif_aead exécute les opérations AEAD en place, c'est-à-dire req->src == req->dst. Lorsque les données d'entrée sont fournies via splice() depuis un fichier ordinaire, le scatterlist de destination contient des références aux pages du cache de pages de ce fichier, ce qui permet au noyau d'écrire dans la copie du cache de pages du fichier.
authencesn(hmac(sha256),cbc(aes)) effectue un scratch-write de 4 octets sur le champ seqno_lo de l'AAD (octets 4 à 7 de l'AAD). Combiné à l'AEAD en place et au chemin splice() ci-dessus, un attaquant peut faire atterrir ces 4 octets dans une page du cache de pages d'un fichier lisible.
Cette modification n'est pas réécrite sur le disque, elle n'affecte que le cache de pages actuel du noyau. Par conséquent, le contenu du fichier sur le disque reste inchangé, mais les lecteurs partageant ce cache de pages verront le contenu altéré. Des fichiers lisibles par tous comme /etc/passwd et /usr/bin/su peuvent être des cibles.
Nécessite une chaîne d'outils Rust et Cargo installés sur la machine.
Compiler tous les binaires Rust :
cargo build --release --bins
Une fois la compilation terminée, les fichiers suivants sont générés :
target/release/cve_2026_31431_detector
target/release/cve_2026_31431_poc
Si le dépôt doit contenir des fichiers précompilés, placez-les dans :
dist/linux-x86_64/cve_2026_31431_detector
dist/linux-x86_64/cve_2026_31431_poc
dist/linux-x86_64/SHA256SUMS
Ne committez pas tout le répertoire target/ ; il contient les artefacts intermédiaires de Cargo et le cache local.
Compiler uniquement le détecteur non destructif :
cargo build --release --bin cve_2026_31431_detector
Compiler uniquement la version Rust de poc.py :
cargo build --release --bin cve_2026_31431_poc
Le détecteur Rust non destructif est recommandé :
./target/release/cve_2026_31431_detector
echo $?
Vous pouvez également l'exécuter directement via Cargo :
cargo run --release --bin cve_2026_31431_detector
echo $?
Utilisation du détecteur Python :
python3 test_cve_2026_31431.py
echo $?
Signification des codes de sortie :
| Code de sortie | Signification |
|---|---|
0 | Aucune vulnérabilité détectée, ou les conditions préalables ne sont pas remplies, par exemple / indisponible. |
Interprétation courante des sorties :
Opérations effectuées par le détecteur :
AF_ALG et de authencesn(hmac(sha256),cbc(aes)).sendmsg et définit le seqno_lo de l'AAD sur le marqueur PWND.splice() dans la socket op AF_ALG.recv() pour déclencher l'exécution de l'algorithme.Le détecteur ne modifie pas /usr/bin/su, /etc/passwd ni aucun autre fichier système. Le fichier sentinelle temporaire est supprimé à la sortie.
Version Rust de poc.py :
./target/release/cve_2026_31431_poc
ou :
cargo run --release --bin cve_2026_31431_poc
Remarque : ce PoC ouvre /usr/bin/su selon la logique de poc.py, corrompt sa copie dans le cache de pages via la primitive de la vulnérabilité, puis exécute su. Ce n'est pas un processus de détection non destructif, il ne doit être exécuté que dans un environnement de test autorisé.
python3 exploit_cve_2026_31431.py
python3 exploit_cve_2026_31431.py --shell
Ce script recherche le champ UID de l'utilisateur actuel dans /etc/passwd et tente de modifier l'UID dans le cache de pages en 0000. Le fichier /etc/passwd sur le disque n'est pas modifié, mais les processus système lisant le cache de pages peuvent voir le contenu altéré.
Conditions restrictives :
1000 à 9999.nscd, sssd, systemd-userdbd, peuvent masquer les modifications du cache de pages de /etc/passwd./etc/passwd doit rester présent entre le patch et l'exécution de su.Nettoyage du cache de pages :
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)"
Si vous avez déjà obtenu un shell root, vous pouvez également exécuter :
echo 3 > /proc/sys/vm/drop_caches
Un redémarrage efface également l'état du cache de pages.
En attendant le correctif du noyau de la distribution, vous pouvez désactiver algif_aead :
sudo tee /etc/modprobe.d/disable-algif-aead.conf <<<'install algif_aead /bin/false'
sudo rmmod algif_aead 2>/dev/null
Après application de la mesure d'atténuation, le détecteur devrait normalement afficher Conclusion du test : aucune vulnérabilité trouvée et indiquer que les conditions préalables de déclenchement ne sont pas remplies, avec un code de sortie de 0.
L'approche du correctif en amont consiste à rétablir le traitement non en place des opérations AEAD, afin d'éviter que les pages du cache de pages n'entrent dans un scatterlist de destination inscriptible.
| Fichier | Description |
|---|
test_cve_2026_31431.py | Détecteur Python non destructif. Ne manipule que des fichiers sentinelles temporaires, ne touche pas aux fichiers système. |
src/main.rs | Détecteur Rust non destructif. La logique de détection et les codes de sortie sont identiques à ceux du détecteur Python. |
src/bin/poc.rs | Version Rust de poc.py. Corrompt le cache de pages de /usr/bin/su et exécute su. |
poc.py | PoC Python. |
exploit_cve_2026_31431.py | LPE Python. Tente d'obtenir un shell root en corrompant le cache de pages de /etc/passwd. |
AF_ALGauthencesn2 | Vulnérabilité à CVE-2026-31431 détectée. |
1 | Erreur pendant le test, le résultat ne peut pas servir de base pour juger de la vulnérabilité. |
| Sortie | Conclusion |
|---|
Conclusion du test : aucune vulnérabilité trouvée | Aucune vulnérabilité détectée, ou les conditions préalables de déclenchement ne sont pas remplies. |
Conclusion du test : vulnérabilité CVE-2026-31431 présente | Le marqueur PWND a bien atterri dans la page du cache de pages splicée, la vulnérabilité est présente. |
Conclusion du test : vulnérabilité CVE-2026-31431 probablement présente | Le cache de pages a été modifié, même si le marqueur n'a pas atterri à l'emplacement attendu, le système doit être considéré comme affecté. |
Erreur pendant le test, impossible de déterminer la présence de la vulnérabilité | Échec de la détection, code de sortie 1, il faut examiner le message d'erreur puis relancer. |