Protections de libc

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Application de l’alignement des chunks

Malloc alloue de la mémoire en groupes de 8 octets (32-bit) ou 16 octets (64-bit). Cela signifie que la fin des chunks sur les systèmes 32-bit doit s’aligner sur 0x8, et sur les systèmes 64-bit sur 0x0. La fonctionnalité de sécurité vérifie que chaque chunk s’aligne correctement à ces emplacements spécifiques avant d’utiliser un pointeur depuis un bin.

Avantages en matière de sécurité

L’application de l’alignement des chunks sur les systèmes 64-bit renforce significativement la sécurité de Malloc en limitant le placement de fake chunks à seulement 1 adresse sur 16. Cela complique les efforts d’exploitation, surtout dans les scénarios où l’utilisateur a un contrôle limité sur les valeurs d’entrée, rendant les attaques plus complexes et plus difficiles à exécuter avec succès.

  • Fastbin Attack on __malloc_hook

Les nouvelles règles d’alignement dans Malloc contrent également une attaque classique impliquant __malloc_hook. Auparavant, les attaquants pouvaient manipuler les tailles de chunks pour écraser ce pointeur de fonction et obtenir une code execution. Désormais, l’exigence stricte d’alignement garantit que de telles manipulations ne sont plus viables, fermant une voie d’exploitation courante et améliorant la sécurité globale.

Note : Depuis glibc 2.34 les hooks hérités (__malloc_hook, __free_hook, etc.) sont retirés de l’ABI exportée. Les exploits modernes ciblent désormais d’autres pointeurs de fonction écrits (par ex. tcache per-thread struct, vtable-style callbacks) ou s’appuient sur setcontext, _IO_list_all primitives, etc.

Pointer Mangling on fastbins and tcache

Pointer Mangling est une amélioration de sécurité utilisée pour protéger les fastbin et tcache Fd pointers dans les opérations de gestion de mémoire. Cette technique aide à prévenir certains types de tactiques d’exploitation mémoire, en particulier celles qui ne nécessitent pas d’informations mémoire leaked ou qui manipulent des emplacements mémoire directement par rapport à des positions connues (relative overwrites).

Le cœur de cette technique est une formule d’obfuscation :

New_Ptr = (L >> 12) XOR P

  • L est la Storage Location du pointeur.
  • P est le véritable fastbin/tcache Fd Pointer.

La raison du décalage binaire de 12 bits de la storage location (L) vers la droite avant l’opération XOR est critique. Cette manipulation s’attaque à une vulnérabilité inhérente à la nature déterministe des 12 bits de poids faible des adresses mémoire, qui sont typiquement prévisibles en raison des contraintes d’architecture système. En décalant les bits, la portion prévisible est retirée de l’équation, améliorant l’entropie du nouveau pointeur manglé et protégeant ainsi contre les exploits qui s’appuient sur la prévisibilité de ces bits.

Ce pointeur manglé exploite la randomisation existante fournie par Address Space Layout Randomization (ASLR), qui randomise les adresses utilisées par les programmes pour rendre difficile la prédiction du layout mémoire d’un processus.

Le Demangling du pointeur pour récupérer l’adresse originale implique l’utilisation du même XOR. Ici, le pointeur manglé est traité comme P dans la formule, et lorsqu’il est XORé avec la storage location inchangée (L), cela révèle le pointeur original. Cette symétrie dans le mangling et le demangling garantit que le système peut encoder et décoder les pointeurs efficacement sans surcharge significative, tout en augmentant substantiellement la sécurité contre les attaques qui manipulent des pointeurs mémoire.

Avantages en matière de sécurité

Pointer mangling vise à empêcher les overwrites partiels et complets de pointeurs dans la gestion du heap, une amélioration de sécurité significative. Cette fonctionnalité impacte les techniques d’exploitation de plusieurs façons :

  1. Prévention des Bye Byte Relative Overwrites : Auparavant, les attaquants pouvaient modifier une partie d’un pointeur pour rediriger des chunks du heap vers d’autres emplacements sans connaître les adresses exactes, une technique visible dans l’exploit leakless House of Roman. Avec pointer mangling, de tels overwrites relatifs sans un heap leak exigent maintenant du brute forcing, réduisant drastiquement leurs chances de succès.
  2. Augmentation de la difficulté des attaques sur Tcache Bin/Fastbin : Les attaques courantes qui écrasent des pointeurs de fonction (comme __malloc_hook) en manipulant des entrées fastbin ou tcache sont entravées. Par exemple, une attaque pourrait impliquer de leak une adresse LibC, free un chunk dans le tcache bin, puis écraser le Fd pointer pour le rediriger vers __malloc_hook pour une exécution arbitraire. Avec pointer mangling, ces pointeurs doivent être correctement manglés, nécessitant un heap leak pour une manipulation précise, élevant ainsi la barrière d’exploitation.
  3. Nécessité de heap leaks pour les emplacements non-heap : La création d’un fake chunk dans des zones non-heap (comme le stack, la section .bss, ou PLT/GOT) nécessite désormais également un heap leak en raison du besoin de pointer mangling. Cela étend la complexité d’exploitation de ces zones, similaire à l’exigence pour manipuler des adresses LibC.
  4. Leaking Heap Addresses Becomes More Challenging : Pointer mangling restreint l’utilité des Fd pointers dans les bins fastbin et tcache comme sources de leaks d’adresses du heap. Cependant, les pointeurs dans les unsorted, small, et large bins restent unmangled, et sont donc toujours exploitables pour leak des adresses. Ce changement pousse les attaquants à explorer ces bins pour obtenir des informations exploitables, bien que certaines techniques permettent encore de démangler des pointeurs avant un leak, mais avec des contraintes.

Safe-Linking Bypass (page-aligned leak scenario)

Même avec safe-linking activé (glibc ≥ 2.32), si vous pouvez leak le pointeur manglé et que le chunk corrompu et le chunk victime partagent la même page de 4KB, le pointeur original peut être récupéré uniquement avec l’offset de page :

// leaked_fd is the mangled Fd read from the chunk on the same page
uintptr_t l = (uintptr_t)&chunk->fd;           // storage location
uintptr_t original = (leaked_fd ^ (l >> 12));  // demangle

Cela restaure le Fd et permet le classic tcache/fastbin poisoning. Si les chunks résident sur des pages différentes, il est souvent possible de brute-forcer le décalage de page de 12 bits (0x1000 possibilités) lorsque les schémas d’allocation sont déterministes ou lorsque les plantages sont acceptables (par ex. exploits de type CTF).

Demangling Pointers with a Heap Leak

Caution

Pour une meilleure explication du processus, consultez le billet original ici.

Algorithm Overview

La formule utilisée pour mangler et démangler les pointeurs est :

New_Ptr = (L >> 12) XOR P

L est l’emplacement de stockage et P est le pointeur Fd. Quand L est décalé à droite de 12 bits, il expose les bits les plus significatifs de P, en raison de la nature du XOR, qui donne 0 lorsque des bits identiques sont XORés.

Étapes clés de l’algorithme :

  1. Leak initial des bits les plus significatifs : En XORant le L décalé avec P, on obtient effectivement les 12 bits supérieurs de P parce que la portion décalée de L sera zéro, laissant les bits correspondants de P inchangés.
  2. Récupération des bits du pointeur : Étant donné que XOR est réversible, connaître le résultat et un des opérandes permet de calculer l’autre opérande. Cette propriété est utilisée pour déduire l’ensemble des bits de P en XORant successivement des ensembles de bits connus avec des parties du pointeur manglé.
  3. Démanglage itératif : Le processus est répété, chaque fois en utilisant les bits nouvellement découverts de P à partir de l’étape précédente pour décoder le segment suivant du pointeur manglé, jusqu’à récupération complète.
  4. Gestion des bits déterministes : Les 12 bits finaux de L sont perdus à cause du décalage, mais ils sont déterministes et peuvent être reconstruits après le processus.

Vous pouvez trouver une implémentation de cet algorithme ici : https://github.com/mdulin2/mangle

Pointer Guard

Pointer Guard est une technique d’atténuation des exploits utilisée dans glibc pour protéger les pointeurs de fonctions stockés, en particulier ceux enregistrés par des appels de bibliothèque comme atexit(). Cette protection consiste à mélanger les pointeurs en les XORant avec un secret stocké dans les données de thread (fs:0x30) et en appliquant une rotation binaire. Ce mécanisme vise à empêcher les attaquants de détourner le contrôle d’exécution en écrasant des pointeurs de fonction.

Bypassing Pointer Guard with a leak

  1. Comprendre les opérations de Pointer Guard : Le scrambling (mangling) des pointeurs est effectué via la macro PTR_MANGLE qui XORe le pointeur avec un secret 64 bits puis effectue une rotation à gauche de 0x11 bits. L’opération inverse pour récupérer le pointeur original est gérée par PTR_DEMANGLE.
  2. Stratégie d’attaque : L’attaque se base sur une approche known-plaintext, où l’attaquant doit connaître à la fois la version originale et la version manglée d’un pointeur pour déduire le secret utilisé pour le mangling.
  3. Exploitation de plaintexts connus :
  • Identification des pointeurs de fonctions fixes : En examinant le code source de glibc ou les tables de pointeurs de fonction initialisées (comme __libc_pthread_functions), un attaquant peut trouver des pointeurs de fonction prévisibles.
  • Calcul du secret : En utilisant un pointeur de fonction connu tel que __pthread_attr_destroy et sa version manglée issue de la table de pointeurs, le secret peut être calculé en effectuant une rotation inverse (rotation à droite) du pointeur manglé puis en le XORant avec l’adresse de la fonction.
  1. Plaintexts alternatifs : L’attaquant peut aussi expérimenter le mangling de pointeurs avec des valeurs connues comme 0 ou -1 pour voir si cela produit des motifs identifiables en mémoire, révélant potentiellement le secret lorsque ces motifs sont trouvés dans des dumps mémoire.
  2. Application pratique : Après avoir calculé le secret, un attaquant peut manipuler les pointeurs de manière contrôlée, contournant essentiellement la protection Pointer Guard dans une application multithreadée, à condition de connaître la base de libc et de pouvoir lire des emplacements mémoire arbitraires.

GLIBC Tunables & Recent Loader Bugs

Le loader dynamique analyse GLIBC_TUNABLES avant le démarrage du programme. Des bugs de mauvaise analyse ici affectent directement libc avant que la plupart des mitigations n’interviennent. Le bug “Looney Tunables” de 2023 (CVE-2023-4911) en est un exemple : une valeur GLIBC_TUNABLES trop longue déborde les buffers internes dans ld.so, permettant une escalade de privilèges sur de nombreuses distributions lorsqu’elle est combinée à des binaires SUID. L’exploitation ne nécessite que la création d’un environnement adapté et l’invocation répétée du binaire cible ; pointer guard ou safe-linking ne l’empêchent pas car la corruption se produit dans le loader avant la mise en place du heap.

References

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks