Loading AI tools
De Wikipédia, l'encyclopédie libre
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.
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 |
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:
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].
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.
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].
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é.
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:
Microsoft adopta cette mitigation en 2017 à partir de Windows 10, sous le nom d'Arbitrary Code Guard[8]
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]:
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.
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]
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].
Afin de complexifier les attaques par dépassement de tampon sur la pile d'appel, PaX rend aléatoire son adresse[18].
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].
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:
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].
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
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].
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], …
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 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].
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 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 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.
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:
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].
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.