Aller au contenu

PaX

Un article de Wikipédia, l'encyclopédie libre.
PaX
Description de l'image Pax tux.png.

Informations
Créateur PaX Team
Première version
État du projet en développement actif
Écrit en C
Environnement Linux
Type patch
Licence GPLv2
Documentation https://pax.grsecurity.net/docs/
Site web https://pax.grsecurity.net

PaX est un correctif (patch) de sécurité pour le noyau Linux créé en octobre 2000[1] par un collectif nommé PaX Team (en français, L'Équipe PaX), aujourd'hui composé d'un seul développeur utilisant le pseudonyme pipacs.

Le modèle de menace de PaX est un attaquant, local ou distant, possédant une primitive de lecture/écriture arbitraire de la mémoire du noyau ou de l'espace utilisateur[2]. Ce qui se traduit par 3 familles d'attaques:

  • celles qui introduisent et exécutent un code arbitraire, fréquemment via un shellcode;
  • celles qui essaient d'exécuter du code déjà existant, mais dans un contexte autre que celui prévu par le programmeur, à l'aide de constructions telle que return-to-libc attack;
  • celles qui essaient d'exécuter du code avec des données arbitraires.

Pour défendre contre ce modèle, PaX inventa un grand nombre de mécanisme de sécurité qui ont été largement adopté au sein de l'industrie: la protection de l'espace exécutable via l'implémentation de W^X (ayant mené à son implantation matérielle via le bit NX), l'ASLR, l'intégrité de flux de contrôle (CFI), … La plupart de ces mécanismes n'ont pas pour but de détecter toutes les vulnérabilités, mais de les rendre inexploitables.

Étant basé sur le noyau Linux, PaX peut être utilisé sur toutes les architectures qu'il supporte.

Le , une vulnérabilité dans l'implémentation du VMA Mirroring est publiée, accompagnée d'exploits[3],[4]. À la suite de cet évènement, en avril 2005, PaX Team annonce la fin du développement de PaX, ce qui n'aura finalement pas lieu: faute de candidat à la reprise du développement, l'équipe originale a continué[4].

Les techniques utilisées par PaX

[modifier | modifier le code]

Protection de zones mémoires contenant du code exécutable

[modifier | modifier le code]

La protection de zones mémoires contenant du code exécutable vise à interdire à un attaquant d'introduire du code arbitraire. La technique principale pour ce faire est de ne jamais avoir de code à la fois accessible en écriture et en exécution, en utilisant (ou émulant) la fonctionnalité du NX Bit.

PaX_PAGEEXEC

[modifier | modifier le code]

Basée sur une idée du projet freemware/plex86, PAGEEXEC est la première implémentation proposée pour implémenter le bit NX sur les architectures i386 en octobre 2000[1],[5],[2]. L'implémentation repose sur le translation lookaside buffer (TLB), le cache utilisé par l'unité de gestion mémoire. Lors d'une tentative d'accès à une page protégée qui n'est pas encore dans le TLB, en exécution, une faute de protection est levée. Comme sur les processeurs récents le TLB est séparé en un cache pour les exécutions (ITLB) et un cache pour les données (DTLB), PaX peut déterminer s'il s'agit d'une instruction, qui doit alors être interdite[6].

PaX_SEGMEXEC

[modifier | modifier le code]

Créé en octobre 2002, SEGMEXEC émule le fonctionnement du bit NX sur les processeurs IA-32. Cela fonctionne en segmentant la mémoire en deux zones de 1.5 Go chacune. La zone basse (de 0 à 1.5 Go) contient les données non exécutables, c'est-à-dire les données mais aussi instructions (qui peuvent en effet vouloir être lues). La seconde zone, exécutable, en revanche ne contient que les instructions. Les mappings des deux segments pointent vers les mêmes zones de la mémoire physique, ainsi la mémoire vive utilisée n'est pas doublée[6].

Lorsqu'une adresse mémoire doit être exécutée, elle est traduite dans la zone contenant le code exécutable. Si le code n'est pas présent à l'adresse traduite, il s'agit alors d'une tentative d'exécution de code interdite, le programme est alors tué.

PaX_MPROTECT

[modifier | modifier le code]

Introduite en novembre 2000, le but de PAX_MPROTECT est d'interdire l'introduction de nouveau code exécutable dans des processus, en ajoutant des restrictions sur les fonctions mmap et mprotect[7],[6], interdisant:

  • L'allocation mémoire accessible en lecture et écriture;
  • la projection mémoire via mmap en lecture et écriture;
  • l'ajout de permission d'accès en exécution sur une projection mémoire, exceptée pour effectuer des relocations sur un fichier marqué comme ET_DYN ELF
  • l'ajout de permission d'accès en exécution sur une allocation mémoire.

Microsoft adopta cette mitigation en 2017 à partir de Windows 10, sous le nom d'Arbitrary Code Guard[8]

PaX_KERNEXEC

[modifier | modifier le code]

Ajouté à PaX in avril 2003, il s'agit plus ou moins d'une implémentation de PAGEEXEC pour l'espace noyau, basé sur les mêmes mécanismes que SEGMEXEC et PAX_MPROTECT[6],[9]:

  • Un marquage d'autant d'éléments que possible en lecture seule: table d'appels systeme, segment .rodata, IDT, GDT, …
  • L'interdiction d'exécuter du code en espace utilisateur depuis l'espace noyau, en forçant le bit de poids significatif à 1 dans tous les pointeurs sur fonction en espace noyau ainsi que sur les adresses de retour, rendant les adresses de l'espace utilisateur non-canoniques[2].

Trampoline emulation

[modifier | modifier le code]

Les trampolines implémentés par GCC sous la forme de petites portions de code généralement générés sur la pile lors du runtime[10]. Cela nécessite donc de rendre exécutable la pile, ce qu'empêche PaX. Pour éviter que les programmes utilisant cette technique ne soient tués, PaX est capable d'identifier et d'autoriser leur utilisation.

Address space layout randomization

[modifier | modifier le code]

Inventé en juin 2001 par pipacs comme une mesure de sécurité temporaire[11], l'address space layout randomization consiste à rendre certaines adresses de la mémoire virtuelle aléatoires permettant de se prémunir contre l'exploitation de certaines failles (généralement de type dépassement de tampon). Les parties de programmes qui seront placées à des adresses aléatoires sont en général la pile, le tas, la position des bibliothèques, … Cette technique est maintenant utilisée par tous les systèmes d'exploitation modernes: Microsoft l'ajouta à Windows XP SP3 en 2007[12], Apple à macOS en 2007 également, Linux l'obtiendra en 2005[13], …[14]

PaX_RANDKSTACK

[modifier | modifier le code]

Ce plugin rend aléatoire la pile d'appel des processus noyau a chaque appel système, forçant un attaquant à deviner son adresse, mais empêchent également la fuite d'informations par ce biais[15]. Ce plugin fut écrit en réaction à la publication de l'attaque Stackjacking by Jon Oberheide et Dan Rosenberg[16]. Ce plugin fut intégré au noyau linux en 2019 par Elena Reshetova[17].

PaX_RANDUSTACK

[modifier | modifier le code]

Afin de complexifier les attaques par dépassement de tampon sur la pile d'appel, PaX rend aléatoire son adresse[18].

PaX_RANDMMAP

[modifier | modifier le code]

Introduit en 2003, PAX_RANDMMAP rend aléatoire l'adresse de base utilisée par mmap(). ayant pour effet, entre autres, de rendre aléatoire les adresses auxquelles sont chargées les bibliothèques externes[19],[20].

Ségrégation de l'espace noyau et de l'espace utilisateur

[modifier | modifier le code]

PaX_MEMORY_UDEREF

[modifier | modifier le code]

PAX_MEMORY_UDEREF interdit au noyau d'accéder en lecture/écriture à l'espace utilisateur[21]. Elle utilise différentes implémentations suivant les architectures:

  • Sur i386, la segmentation est utilisée, excluant complètement l'espace utilisateur du segment data.
  • Sur SPARC64, UDEREF est fournie de manière native par le processeur.
  • Sur x86_64
    • Utilisation d'une projection de l'espace utilisateur non-exécutable lors de l'exécution de code en espace noyau, via le PGD (page global directory).
    • SMAP sur les processeurs possédant cette fonctionnalité[22].
  • Sur ARMv6+[23]
    • Une technique similaire à celle utilisée sur x86_64 sans support de SMAP.
    • PXN sur les processeurs possédant cette fonctionnalité.

PaX_USERCOPY

[modifier | modifier le code]

PAX_USERCOPY ajoute des vérifications sur la taille des objets sur le tas copiés, y compris partiellement, vers/depuis l'espace utilisateur vers/depuis l'espace noyau. L'idée principale étant que comme les allocations mémoire sont ségrégées par taille, il est possible de retrouver la taille d'une allocation à partir de son adresse mémoire[2].

Elle introduit également une liste-blanche de zones mémoire pouvant être copié vers/depuis l'espace utilisateur, interdisant par exemple les structures contenant les privilèges utilisateur ou les détails des tâches en cours d'être copiées[9].

Cette fonctionnalité fut intégrée dans le noyau Linux par Kees Cook en 2016 sous le nom de CONFIG_HARDENED_USERCOPY[24].

Prévention de fuites de données

[modifier | modifier le code]

PaX_MEMORY_SANITIZE

[modifier | modifier le code]

Cette fonctionnalité efface immédiatement les zones mémoires lorsqu'elles sont rendues au noyau, réduisant ainsi la durée pendant laquelle des informations sensibles comme des mots de passes ou des clefs de chiffrement[9]. Cette approche a deux effets de bord bénéfique

  • Les fuites dues au padding lié à l'alignement mémoire de certaines structures sont réduites;
  • Certaines attaques de type user-after-free utilisant des pointeurs au sein de structures peuvent être détectée: le déréférencement d'un pointeur effacé provoquant un crash.

Cette approche a cependant un coût en performance non-négligeable, aux alentours de 3%. Un sous-ensemble de cette approche, nommé INIT_ON_FREE_DEFAULT_ON, a été accepté dans le noyau linux en 2019, avec un impact sur les performances aux alentours de 7%[25],[26].

Plugins gcc

[modifier | modifier le code]

PaX_SIZE_OVERFLOW

[modifier | modifier le code]

Originellement écrit par Emese "ephox" Révfy, size_overflow vise a détecter les dépassements d'entiers automatiquement. L'idée principale est basée sur l'usage du type intoverflow_t d'anciennes versions de PaX: un entier de taille 64 sur les architectures 32 bits, et 128 bits sur celles a 64 bits, permettant de valider, manuellement, dans certains fonctions critiques que les entiers ne dépassent pas. Le plugin se contente d'effectuer les mêmes vérifications, mais de manière entièrement automatique[27]. Ce plugin a permis, et permet encore, de trouver un grand nombre de failles de sécurité, comme CVE-2013-0914[28], CVE-2013-0913[29], CVE-2013-2141[30], …

PaX_LATENT_ENTROPY

[modifier | modifier le code]

Introduit en 2012[31] et inspiré par le papier "Mining Your Ps and Qs: Detection of Widespread Weak Keys in Network Devices"[32], ce plugin extrait de l'entropie en instrumentant le processus de démarrage du noyau, rendant la génération de matériel cryptographique plus robuste, en particulier dans l'informatique embarquée. Cette approche est similaire à celle utilisée par Larry H. dans sa modification KERNHEAP pour le noyau linux en 2009[33].

PaX_REFCOUNT

[modifier | modifier le code]

PAX_REFCOUNT fut créé en 2008[34]. L'idée est d'utiliser un type spécial pour les compteurs de références, pour lequel il est impossible d'obtenir un dépassement d'entier: au lieu de résulter en un dépassement, le type sature à sa valeur maximale, résultant en une possible fuite mémoire, au lieu d'un dangling pointer[35]. Cette fonctionnalité fut proposée à l'adoption dans le noyau Linux en 2012 par David Windsor[36], puis en 2016 par Elena Reshetova, mais c'est la version de Peter Zijlstra qui fut finalement acceptée en 2017[37] pour des raisons de performance[38].

PaX_MEMORY_STACKLEAK

[modifier | modifier le code]

Créé en avril 2011 en réponse[39] à la publication de l'attaque "Stackjacking" par Jon Oberheide et Dan Rosenberg contournant les mechanisms de sécurité[40], PAX_MEMORY_STACKLEAK efface systématiquement la pile de l'espace noyau avant la fin de chaque appel système, réduisant les informations pouvant être obtenues via une fuite mémoire de la pile. Il convient de noter que les informations poussées sur la pile par l'appel système à l'origine de la fuite mémoire de la pile sont évidemment accessibles, seules celles de appels système précédents ne le sont plus. L'impact en performance se situe aux alentours de 1%[9]. Cette fonctionnalité fut intégrée au noyau Linux en 2018 par Alexander Popov[41].

PaX_MEMORY_STRUCTLEAK

[modifier | modifier le code]

PAX_MEMORY_STRUCTLEAK initialise à zéro certains variables locales en espace noyau pouvant être passées en espace utilisateur, empêchant des fuites de mémoire de l'espace noyau si ces variables ne sont pas complètement initialisées dans le code. Il s'agit d'une approche similaire à PAX_MEMORY_STACKLEAK, fournissant une couverture bien moindre, mais avec des performances bien plus élevées.

PaX_CONSTIFY_PLUGIN

[modifier | modifier le code]

PAX_CONSTIFY_PLUGIN rend constants les types contenant uniquement des pointeurs sur fonctions, réduisant ainsi la surface d'attaque du noyau tout en augmentant marginalement ses performances.

PAX_RAP est une implémentation de CFI, interdisant les changements arbitraires du flux d'exécution en espace noyau, que ce soit via l'écrasement de pointeurs sur fonctions, ou d'adresses de retour sur la pile[42]. Il opère sous un modèle de menace extrêmement large: une primitive de lecture/écriture de contenu arbitraire, sur des adresses arbitraires, un nombre arbitraire de fois, à des instants arbitraires, utilisée pour élever ou abuser de privilèges, avec un budget sur les performances aux alentours de 5%.

Annoncée en 2003[43], RAP fut publié 12 ans plus tard, en 2015, et consiste en deux parties principales.

L'utilisation d'un canari dont la valeur est stockée dans un register (r12 sur x86_64), nécessitant donc deux lectures pour le fuiter: une lecture de la valeur chiffrée, et une adresse mémoire. En espace noyau, il est unique par processus et change à chaque appel système. Les piles des autres processus sont rendues illisibles pour empêcher l'accès à leur canaris.

Graphe de flux de contrôle auto-assemblé basé sur les types
[modifier | modifier le code]

L'idée étant d'utiliser les types de fonctions pour générer les signatures. Par exemple un pointeur sur la fonction ssize_t read(int fd, void buf, size_t count) ne pourra appeler que des fonctions ayant la même signature. Certaines fonctions critiques sont augmentées de types artificiels afin de réduire au maximum les pointeurs pouvant y mener. Afin d'augmenter la ségrégation, les signatures sont découpées en plusieurs groupes:

  • Les signatures positives sont utilisées uniquement pour les fonctions et les pointeurs sur fonction.
  • Les signatures négatives pour les adresses de retour et les retours de fonctions
  • Une signature spécifique est utilisée pour les fonctions qui ne sont jamais appelées par un pointeur,.
  • Une signature spécifique est assignée pour les exceptions de type setjmp/longjmp.

Voici à quoi ressemble une vérification du type de retour d'un appel à une fonction:

call ...
jmp 1f
dq 0xffffffffaabbccdd
1:
...
mov %(rsp),%rcx
cmpq $0xaabbccdd,2(%rcx)
jne .error
retn

Voici à quoi ressemble une vérification du type d'un appel à une fonction:

cmpq $0x11223344,-8(%rax)
jne .error
call *%rax
...
cmpq $0x55667788,-16(%rax)
jne .error
call *%rax
...
dq 0x55667788,0x11223344
func:

L'idée d'utiliser les types des fonctions fut reprise par Microsoft dans son implémentation de CFI nommé XFG en 2021[44], ainsi que par Intel avec IBT[45].

Notes et références

[modifier | modifier le code]
  1. a et b (en) « Bugtraq: announcing PaX », sur seclists.org (consulté le )
  2. a b c et d (en) PaX Team, « 20 Years of PaX », SSTIC, no 2012,‎ (lire en ligne)
  3. (en) PaX VMA Mirroring Privilege Escalation Vulnerability, 5 mars 2005, SecurityFocus
  4. a et b « Le projet PaX compromis », Linuxfr,
  5. (en) PaX Team, « pageexec.old.txt », sur grsecurity.net,
  6. a b c et d (en) Brad Spengler, « PaX - The Guaranteed End of Arbitrary Code Execution »
  7. (en) PaX Team, « mprotect.txt », sur grsecurity.net,
  8. (en-US) Microsoft Edge Blog et Matt Miller, « Mitigating arbitrary native code execution in Microsoft Edge », sur Microsoft Edge Blog, (consulté le )
  9. a b c et d (en) « Grsecurity/Appendix/Grsecurity and PaX Configuration Options - Wikibooks, open books for an open world », sur en.wikibooks.org (consulté le )
  10. (en) « Trampolines for Nested Functions » dans la documentation de GCC
  11. « ASLR | Is OpenBSD secure? », sur isopenbsdsecu.re (consulté le )
  12. (en-US) Archiveddocs, « Windows ISV Software Security Defenses », sur learn.microsoft.com, (consulté le )
  13. « The NX Bit And ASLR - Behind Pwn2Own: Exclusive Interview With Charlie Miller | Tom's Hardware », sur web.archive.org, (consulté le )
  14. « Apple - Mac OS X - Security - Keeps safe from viruses and malware », sur web.archive.org, (consulté le )
  15. PaX Team, randkstack.txt, (lire en ligne)
  16. « Stackjacking Your Way to grsec/PaX Bypass | Jon Oberheide », sur jon.oberheide.org (consulté le )
  17. « x86/entry/64: randomize kernel stack offset upon syscall [LWN.net] », sur lwn.net (consulté le )
  18. (en) PaX Team, « randustack.txt »,
  19. (en) PaX Team, « randmmap.txt », sur grsecurity.net,
  20. (en) Nergal, « The advanced return-into-lib(c) exploits: PaX case study », phrack, vol. 0x0b, no 0x3a,‎ (lire en ligne)
  21. (en) PaX Team, « uderef.txt » [txt], sur grsecurity.net/,
  22. « grsecurity forums • View topic - Supervisor Mode Access Prevention », sur forums.grsecurity.net (consulté le )
  23. « grsecurity - Recent ARM Security Improvements », sur grsecurity.net (consulté le )
  24. « Hardened usercopy [LWN.net] », sur lwn.net (consulté le )
  25. (en-US) « security things in Linux v5.3 « codeblog » (consulté le )
  26. « [v4,1/3] mm: security: introduce init_on_alloc=1 and init_on_free=1 boot options - Patchwork », sur patchwork.kernel.org (consulté le )
  27. « grsecurity forums • View topic - Inside the Size Overflow Plugin », sur forums.grsecurity.net (consulté le )
  28. « LKML: Kees Cook: [PATCH] signal: always clear sa_restorer on execve », sur lkml.org (consulté le )
  29. « LKML: Kees Cook: [PATCH] drm/i915: bounds check execbuffer relocations », sur lkml.org (consulté le )
  30. (en) « kernel/signal.c: stop info leak via the tkill and the tgkill syscalls · torvalds/linux@b9e146d », sur GitHub (consulté le )
  31. PaX Team, « [grsec] new gcc plugin: latent entropy extraction », mon jul 23 16:11:37 edt 2012 (consulté le )
  32. « Widespread Weak Keys in Network Devices - factorable.net », sur factorable.net (consulté le )
  33. « .:: Phrack Magazine ::. », sur phrack.org (consulté le )
  34. « grsecurity - grsecurity 4.12 Updates », sur grsecurity.net (consulté le )
  35. « grsecurity forums • View topic - Guest Blog by Rodrigo Branco: PAX_REFCOUNT Documentation », sur forums.grsecurity.net (consulté le )
  36. « Add PAX_REFCOUNT overflow protection [LWN.net] », sur lwn.net (consulté le )
  37. « refcount_t: Introduce a special purpose refcount type - kernel/git/torvalds/linux.git - Linux kernel source tree », sur git.kernel.org (consulté le )
  38. « kernel-hardening - Re: [RFCv2 PATCH 00/18] refcount_t API + usage », sur www.openwall.com (consulté le )
  39. « grsecurity forums • View topic - Much Ado About Nothing: A Response in Text and Code », sur forums.grsecurity.net (consulté le )
  40. « Stackjackin' 2: Electric Boogaloo | Jon Oberheide », sur jon.oberheide.org (consulté le )
  41. (en) « How STACKLEAK improves Linux kernel security », sur Alexander Popov, (consulté le )
  42. (en) PaX Team, « RAP: RIP ROP » [PDF],
  43. (en) PaX Team, « pax-future.txt » [txt],
  44. (en-US) tom, « eXtended Flow Guard Under The Microscope | Offensive Security », sur OffSec, (consulté le )
  45. (en) « Experimental "FineIBT" Series Published For Linux - Building Atop Intel CET/IBT », sur www.phoronix.com (consulté le )

Articles connexes

[modifier | modifier le code]

Liens externes

[modifier | modifier le code]