Abstrait
1. Introduction
2. Contexte
3. Modèle de menace
4. Recherche de gadgets de fuite de balises
5. Gadgets TIKTAG
6. Attaques réelles
6.1. Attaque de Chrome
7. Évaluation
8. Travaux connexes
9. Conclusion et références
\
Pour démontrer l'exploitabilité des gadgets TIKTAG dans l'atténuation basée sur MTE, cette section développe deux attaques réelles contre Chrome et le noyau Linux (Figure 9). Il existe plusieurs défis pour lancer des attaques réelles en utilisant les gadgets TIKTAG. Premièrement, les gadgets TIKTAG doivent être exécutés dans l'espace d'adressage cible, obligeant l'attaquant à construire ou à trouver des gadgets à partir du système cible. Deuxièmement, l'attaquant doit contrôler et observer l'état du cache pour divulguer les résultats de vérification des balises. Dans ce qui suit, nous démontrons les attaques réelles utilisant les gadgets TIKTAG sur deux systèmes réels : le navigateur Google Chrome (§6.1) et le noyau Linux (§6.2), et discutons des stratégies d'atténuation.
\ 6.1. Attaque de Chrome
Navigateur Un navigateur Web est une surface d'attaque principale pour les attaques basées sur le Web car il traite du contenu Web non fiable, tel que JavaScript et HTML. Nous présentons d'abord le modèle de menace (§6.1.1) et fournissons un gadget TIKTAG construit dans le moteur JavaScript V8 (§6.1.2). Ensuite, nous démontrons l'efficacité des gadgets TIKTAG dans l'exploitation du navigateur (§6.1.3) et discutons des stratégies d'atténuation (§6.1.4).
\ ==6.1.1. Modèle de menace.== Nous suivons le modèle de menace typique des attaques de navigateur Chrome, où l'attaquant vise à exploiter les vulnérabilités de corruption de mémoire dans le processus de rendu. Nous supposons que l'utilisateur victime visite le site Web contrôlé par l'attaquant, qui sert une page Web malveillante. La page Web comprend du HTML et du JavaScript conçus, qui exploitent les vulnérabilités de corruption de mémoire dans le processus de rendu de la victime. Nous supposons que toutes les techniques d'atténuation de pointe de Chrome sont en place, notamment ASLR [18], CFI [15], l'isolation de site [53] et le bac à sable V8 [56]. De plus, en tant que défense orthogonale, nous supposons que le processus de rendu active le marquage MTE aléatoire dans PartitionAlloc [2].
\ ==6.1.2. Construction du gadget TIKTAG.== Dans l'environnement JavaScript V8, TIKTAG-v2 a été construit avec succès et a divulgué les balises MTE de n'importe quelle adresse mémoire. Cependant, nous n'avons pas trouvé de gadget TIKTAG-v1 constructible, car la contrainte temporelle stricte entre BR et CHECK n'était pas réalisable dans notre technique d'évasion spéculative du bac à sable V8 (§A).
Gadget V8 TikTag-v2. La figure 8 est le gadget TIKTAG-v2 construit dans le moteur JavaScript V8 et son pseudo-code C après compilation JIT. Avec ce gadget, l'attaquant peut savoir si la balise devinée Tg correspond à la balise Tm attribuée à target_addr. L'attaquant prépare trois tableaux, slow, victim, probe, et une valeur idx. slow est un Unit8Array d'une longueur de 64 et est accédé dans BR pour déclencher la mauvaise prédiction de branche. victim est un Float64Array de longueur 64, qui est accédé pour déclencher le transfert store-to-load. probe est un Uint8Array de longueur 512, et est accédé dans
\ TEST pour divulguer le résultat de vérification de balise. Une valeur idx de type Number est utilisée dans l'accès hors limites de victim. La valeur idx est choisie de sorte que victim[idx] pointe vers targetaddr avec une balise devinée Tg (c'est-à-dire (Tg«56)|targetaddr). Pour accéder spéculativement à target_addr en dehors du bac à sable V8, nous avons exploité la technique d'évasion spéculative du bac à sable V8 que nous avons découverte au cours de nos recherches, que nous détaillons dans §A. La ligne 8 de la figure 8a est le bloc BR du gadget TIKTAG-v2, déclenchant une mauvaise prédiction de branche avec slow[0].
\ Les lignes 12-13 constituent le bloc CHECK, qui effectue le transfert store-to-load avec victim[idx], accédant à target_addr avec une balise devinée Tg. Lorsque ce code est compilé JIT (Figure 8b), une vérification des limites est effectuée, comparant idx avec victim.length. Si idx est un index hors limites, le code renvoie undefined, mais si le champ victim.length prend beaucoup de temps à charger, le CPU exécute spéculativement les instructions store et load suivantes.
\ Ensuite, la ligne 17 implémente le bloc TEST, qui accède au probe avec la valeur transférée val comme index. Encore une fois, une vérification des limites sur val par rapport à la longueur de probe est précédée, mais cette vérification réussit car PROBEOFFSET est plus petit que la longueur du tableau probe. En conséquence, probe[PROBEOFFSET] est mis en cache uniquement lorsque le transfert store-to-load réussit, ce qui est le cas lorsque Tg correspond à Tm.
\ ==6.1.3. Attaque de contournement MTE de Chrome.== La figure 9a illustre l'attaque globale de contournement MTE sur le navigateur Chrome avec une primitive arbitraire de fuite de balises des gadgets TIKTAG. Nous supposons une vulnérabilité de dépassement de tampon dans le processus de rendu, où l'exploitation d'une vulnérabilité temporelle (par exemple, use-after-free) est largement la même. La vulnérabilité déborde un pointeur (c'est-à-dire vuln_ptr) vers un objet vulnérable (c'est-à-dire objvuln), corrompant l'objet adjacent (c'est-à-dire objtarget).
\ Avec l'application MTE de PartitionAlloc, deux objets ont des balises différentes avec une probabilité de 14/15. Pour éviter de déclencher une exception, l'attaquant doit s'assurer que les balises d'objvuln et d'objtarget sont identiques. TIKTAG-v2 peut être utilisé pour divulguer la balise d'objvuln ( 1 ) et d'objtarget ( 2 ). Si les deux balises divulguées sont identiques, l'attaquant exploite la vulnérabilité, ce qui ne déclencherait pas de défaut de vérification de balise ( 3 ). Sinon, l'attaquant libère et réalloue objtarget et revient à la première étape jusqu'à ce que les balises correspondent.
\ ==Déclenchement du canal latéral de cache.== Pour exploiter avec succès un gadget TIKTAG, l'attaquant doit satisfaire aux exigences suivantes :
i) entraînement de branche,
ii) contrôle du cache, et
iii) mesure du cache. Les trois exigences peuvent être satisfaites en JavaScript.
Premièrement, l'attaquant peut entraîner le prédicteur de branche en exécutant le gadget avec slow[0] non nul et idx dans les limites, et déclencher la mauvaise prédiction de branche dans BR avec une valeur nulle dans slow[0] et idx hors limites.
Deuxièmement, l'attaquant peut évincer les lignes de cache de slow[0], victim.length et probe[PROBE_OFFSET] avec des techniques d'éviction de cache JavaScript [8, 21, 70].
Troisièmement, l'attaquant peut mesurer l'état du cache de probe[PROBE_OFFSET] avec un minuteur haute résolution basé sur SharedArrayBuffer [16, 58].
\ ==Exploitation des vulnérabilités de corruption de mémoire.== Étant donné les balises MTE divulguées, l'attaquant peut exploiter les vulnérabilités de corruption de mémoire spatiales et temporelles dans le moteur de rendu. La stratégie d'attaque est largement la même que les attaques traditionnelles de corruption de mémoire, mais doit s'assurer que la vulnérabilité ne déclenche pas de défaut de vérification de balise en utilisant les balises divulguées. Nous détaillons davantage la stratégie d'attaque dans §C.
\ ==6.1.4. Atténuation.== Pour atténuer les attaques de contournement MTE basées sur les gadgets TIKTAG dans le processus de rendu du navigateur, les atténuations suivantes peuvent être employées :
i) Bac à sable conscient de l'exécution spéculative : Pour empêcher les attaquants de lancer des attaques basées sur TIKTAG à partir d'un environnement en bac à sable comme le bac à sable V8, le bac à sable peut être fortifié en empêchant tout accès mémoire spéculatif au-delà de la région mémoire du bac à sable. Bien que les navigateurs Web modernes emploient un bac à sable pour isoler les contenus Web non fiables du moteur de rendu, ils négligent souvent les chemins spéculatifs.
\ Par exemple, le bac à sable Chrome V8 [56] et le bac à sable Safari Webkit [1] ne médiatisent pas complètement les chemins spéculatifs [27]. Sur la base des techniques actuelles de compression de pointeurs [64], les chemins spéculatifs peuvent être restreints à la région du bac à sable en masquant les bits élevés des pointeurs.
\ ii) Barrière de spéculation : Comme suggéré dans §5, placer une barrière de spéculation après BR pour les gadgets TIKTAG potentiels peut empêcher les attaques de fuite de balises spéculatives. Cependant, cette atténuation peut ne pas être applicable dans l'environnement de navigateur critique en termes de performances, car elle peut introduire une surcharge de performance significative.
\ iii) Prévention de la construction de gadgets : Comme suggéré dans §5.2, le gadget TIKTAG-v2 peut être atténué en ajoutant des instructions entre les instructions store et load. Un gadget TIKTAGv1, bien que nous n'en ayons pas trouvé d'exploitable, peut être atténué en ajoutant des instructions entre une branche et les accès mémoire, comme décrit dans §5.1.
\ 6.2. Attaque du noyau Linux
Le noyau Linux sur ARM est largement utilisé pour les appareils mobiles, les serveurs et les appareils IoT, ce qui en fait une cible d'attaque attractive. L'exploitation d'une vulnérabilité de corruption de mémoire dans le noyau peut escalader les privilèges de l'utilisateur, et donc MTE est un mécanisme de protection prometteur pour le noyau Linux. Les attaques basées sur TIKTAG contre le noyau Linux posent des défis uniques différents de l'attaque du navigateur (§6.1).
\ Cela est dû au fait que l'espace d'adressage de l'attaquant est isolé de l'espace d'adressage du noyau où le gadget sera exécuté. Dans ce qui suit, nous présentons d'abord le modèle de menace du noyau Linux (§6.2.1) et fournissons un gadget TIKTAG de preuve de concept que nous avons découvert dans le noyau Linux (§6.2.2). Enfin, nous démontrons l'efficacité des gadgets TIKTAG dans l'exploitation des vulnérabilités du noyau Linux (§6.2.3).
\ ==6.2.1. Modèle de menace.== Le modèle de menace ici est largement le même que celui des attaques typiques d'escalade de privilèges contre le noyau. Plus précisément, nous nous concentrons sur le noyau Linux Android basé sur ARM, durci avec les protections de noyau par défaut (par exemple, KASLR, SMEP, SMAP et CFI). Nous supposons en outre que le noyau est durci avec une solution de marquage aléatoire MTE, similaire aux solutions MTE prêtes pour la production, Scudo [3].
\ Pour être précis, chaque objet mémoire est marqué de manière aléatoire, et une balise aléatoire est attribuée lorsqu'un objet est libéré, empêchant ainsi les corruptions de mémoire spatiales et temporelles. L'attaquant est capable d'exécuter un processus non privilégié et vise à escalader ses privilèges en exploitant les vulnérabilités de corruption de mémoire dans le noyau. On suppose que l'attaquant connaît les vulnérabilités de corruption de mémoire du noyau mais ne connaît aucune balise MTE de la mémoire du noyau. Le déclenchement de la corruption de mémoire entre les objets du noyau avec
\ des balises non correspondantes déclencherait un défaut de vérification de balise, ce qui est indésirable pour les exploits réels. Un défi critique dans cette attaque est que le gadget doit être construit en réutilisant le code noyau existant et exécuté par les appels système que l'attaquant peut invoquer. Comme l'architecture ARMv8 sépare les tables de pages utilisateur et noyau, les gadgets de l'espace utilisateur ne peuvent pas accéder spéculativement à la mémoire du noyau. Cette configuration est très différente du modèle de menace d'attaque du navigateur (§6.1), qui a exploité le code fourni par l'attaquant pour construire le gadget. Nous avons également exclu la construction de gadgets basée sur eBPF [17, 28], car eBPF n'est pas disponible pour le processus Android non privilégié [33].
\ ==6.2.2. Gadget kernel TikTag==. Comme décrit dans §4.1, les gadgets TIKTAG doivent répondre à plusieurs exigences, et chaque exigence entraîne des défis dans l'environnement du noyau.
Premièrement, dans BR, une mauvaise prédiction de branche doit être déclenchée avec cond_ptr, qui doit être contrôlable depuis l'espace utilisateur. Étant donné que les processeurs AArch64 récents isolent l'entraînement de prédiction de branche entre l'utilisateur et le noyau [33], l'entraînement de branche doit être effectué depuis l'espace noyau.
Deuxièmement, dans CHECK, guessptr doit être déréférencé. guessptr doit être conçu depuis l'espace utilisateur de sorte qu'il intègre une balise devinée (Tg) et pointe vers l'adresse du noyau (c'est-à-dire target_addr) pour divulguer la balise (Tm). Contrairement à l'environnement JavaScript du navigateur (§6.1), les données fournies par l'utilisateur sont fortement nettoyées dans les appels système, il est donc difficile de créer un pointeur de noyau arbitraire.
\ Par exemple, accessok() garantit que le pointeur fourni par l'utilisateur pointe vers l'espace utilisateur, et la macro arrayindexnospec empêche l'accès hors limites spéculatif avec l'index fourni par l'utilisateur. Ainsi, guessptr doit être un pointeur de noyau existant, en particulier le pointeur vulnérable qui provoque la corruption de mémoire. Par exemple, un pointeur pendant dans use-after-free (UAF) ou un pointeur hors limites dans un dépassement de tampon peut être utilisé. Enfin, dans TEST, testptr doit être déréférencé, et testptr doit être accessible depuis l'espace utilisateur. Pour faciliter la mesure de l'état du cache, test_ptr doit être un pointeur d'espace utilisateur fourni via un argument d'appel système.
\ ==Gadgets découverts.== Nous avons analysé manuellement le code source du noyau Linux pour trouver le gadget TIKTAG répondant aux exigences susmentionnées. En conséquence, nous avons trouvé un gadget TIKTAG-v1 potentiellement exploitable dans sndtimeruserread() (Figure 10). Ce gadget répond aux exigences de TIKTAG-v1 (§5.1). À la ligne 10 (c'est-à-dire BR), l'instruction switch déclenche une mauvaise prédiction de branche avec une valeur contrôlable par l'utilisateur tu->tread (c'est-à-dire condptr). Aux lignes 14-17 (c'est-à-dire CHECK), tread (c'est-à-dire guessptr) est déréférencé par quatre instructions de chargement. tread pointe vers un objet struct sndtimer_tread64 que l'attaquant peut allouer et libérer arbitrairement.
\ Si une vulnérabilité temporelle transforme tread en pointeur pendant, il peut être utilisé comme guessptr. À la ligne 20, (c'est-à-dire TEST), un tampon de pointeur d'espace utilisateur (c'est-à-dire testptr) est déréférencé dans copytouser. Comme ce gadget n'est pas directement accessible depuis l'espace utilisateur, nous avons apporté une légère modification au code du noyau ; nous avons supprimé le retour anticipé pour le cas par défaut à la ligne 6. Cela garantit que le tampon n'est accessible que dans le chemin spéculatif pour observer la différence d'état du cache due à l'exécution spéculative.
\ Bien que cette modification ne soit pas réaliste dans un scénario réel, elle démontre l'exploitabilité potentielle du gadget si des modifications de code similaires sont apportées. Nous avons découvert plusieurs autres gadgets potentiellement exploitables, mais nous n'avons pas pu observer la différence d'état du cache entre la correspondance et la non-correspondance des balises. Néanmoins, nous pensons qu'il existe un fort potentiel pour exploiter ces gadgets. Le lancement d'attaques basées sur TIKTAG implique une ingénierie complexe et sensible, et nous n'avons donc pas pu expérimenter tous les cas possibles.
\ En particulier, TIKTAG-v1 s'appuie sur la réduction de spéculation sur les événements de mauvais chemin, qui peuvent également inclure des défauts de traduction d'adresse ou d'autres exceptions dans le chemin de mauvaise prédiction de branche. Comme les appels système impliquent des flux de contrôle complexes, la réduction de spéculation peut ne pas être déclenchée comme prévu. De plus, plusieurs gadgets peuvent devenir exploitables lorsque le code du noyau change. Par exemple, un gadget TIKTAG-v1 dans ip6mr_ioctl() n'a pas présenté de comportement de fuite de balise MTE lorsqu'il a été appelé depuis son chemin d'appel système (c'est-à-dire ioctl). Cependant, le gadget présentait une fuite de balise lorsqu'il a été porté vers d'autres appels système (par exemple, write) avec un flux de contrôle simple.
\ ==6.2.3. Attaque de contournement MTE du noyau.== La figure 9b illustre les attaques de contournement MTE sur le noyau Linux. En prenant une vulnérabilité use-afterfree comme exemple, nous supposons que l'attaquant a identifié un gadget TIKTAG correspondant, SysTikTagUAF(), capable de divulguer le résultat de vérification de balise du pointeur pendant créé par la vulnérabilité. Par exemple, le gadget TIKTAG-v1 dans sndtimeruser_read() (Figure 10) peut divulguer le résultat de vérification de balise de tread, qui peut devenir un pointeur pendant par une vulnérabilité use-after-free ou double-free.
\ L'attaque se déroule comme suit : Premièrement, l'attaquant libère un objet du noyau (c'est-à-dire objvuln) et laisse son pointeur (c'est-à-dire vuln_ptr) comme pointeur pendant ( 1 ). Ensuite, l'attaquant alloue un autre objet du noyau (c'est-à-dire objtarget) à l'adresse d'objvuln avec SysAllocTarget() ( 2 ). Ensuite, l'attaquant invoque SysTikTag() avec un tampon d'espace utilisateur (c'est-à-dire ubuf) ( 3 ), et divulgue le résultat de vérification de balise (c'est-à-dire Tm == Tg) en mesurant la latence d'accès d'ubuf ( 4 ). Si les balises correspondent, l'attaquant déclenche SysExploitUAF(), un appel système qui exploite la vulnérabilité use-after-free ( 5 ). Sinon, l'attaquant réalloue objtarget jusqu'à ce que les balises correspondent.
\ ==Déclenchement du canal latéral de cache.== Comme dans §6.1.3, une exploitation réussie du gadget TIKTAG nécessite i) un entraînement de branche, ii) un contrôle du cache et iii) une mesure du cache. Pour l'entraînement de branche, l'attaquant peut entraîner le prédicteur de branche et déclencher la spéculation avec des conditions de branche contrôlées par l'utilisateur depuis l'espace utilisateur. Pour le contrôle du cache, l'attaquant peut vider le tampon d'espace utilisateur (c'est-à-dire ubuf), tandis que l'adresse mémoire du noyau peut être évincée par rebond de ligne de cache [25]. Pour la mesure du cache, la latence d'accès d'ubuf peut être mesurée avec le compteur virtuel (c'est-à-dire CNTVCT_EL0) ou un minuteur basé sur un compteur de mémoire (c'est-à-dire une résolution proche du cycle CPU).
\ ==Exploitation des vulnérabilités de corruption de mémoire.== Les gadgets TIKTAG permettent de contourner MTE et d'exploiter les vulnérabilités de corruption de mémoire du noyau. L'attaquant peut invoquer le gadget TIKTAG dans le noyau pour déclencher spéculativement la corruption de mémoire et obtenir le résultat de vérification de balise. Ensuite, l'attaquant peut obtenir le résultat de vérification de balise et déclencher la corruption de mémoire uniquement si les balises correspondent. Nous détaillons le processus d'attaque de contournement MTE du noyau Linux dans §D.
\ ==6.2.4. Atténuation.== Pour atténuer le gadget TIKTAG dans le noyau Linux, les développeurs du noyau doivent envisager les atténuations suivantes :
i) Barrière de spéculation : Les barrières de spéculation peuvent atténuer efficacement le gadget TIKTAG-v1 dans le noyau Linux. Pour empêcher les attaquants de divulguer le résultat de vérification de balise via le tampon d'espace utilisateur, les fonctions du noyau qui accèdent aux adresses de l'espace utilisateur, telles que copytouser et copyfromuser, peuvent être durcies avec des barrières de spéculation. Comme décrit dans §5.1, la fuite des résultats de vérification de balise avec un accès store peut être atténuée en plaçant une barrière de spéculation avant l'accès store (c'est-à-dire TEST).
\ Par exemple, pour atténuer les gadgets exploitant copytouser, une barrière de spéculation peut être insérée avant l'invocation de copytouser. Pour les gadgets utilisant l'accès load au tampon d'espace utilisateur, les barrières atténuent les gadgets si elles sont insérées entre la branche et l'accès mémoire du noyau (c'est-à-dire CHECK). Par exemple, pour atténuer les gadgets exploitant copyfromuser, les développeurs du noyau doivent analyser soigneusement la base de code du noyau pour trouver le modèle de branche conditionnelle, d'accès mémoire du noyau et de copyfromuser(), et insérer une barrière de spéculation entre la branche et l'accès mémoire du noyau.
\ ii) Prévention de la construction de gadgets : Pour éliminer les gadgets TIKTAG potentiels dans le noyau Linux, le code source du noyau peut être analysé et corrigé. Comme les gadgets TIKTAG peuvent également être construits par des optimisations du compilateur, une analyse binaire peut être effectuée. Pour chaque gadget découvert, les instructions peuvent être réorganisées ou des instructions supplémentaires peuvent être insérées pour empêcher la construction du gadget, en suivant les stratégies d'atténuation dans §5.1 et §5.2.
:::info Auteurs :
:::
:::info Cet article est disponible sur arxiv sous licence CC 4.0.
:::
\


