
Analyse technique et preuve de concept pour CVE-2024-45200, un débordement de tampon basé sur la pile dans la bibliothèque réseau P2P Pia de Mario Kart 8 Deluxe, permettant un crash à distance et une RCE potentielle sur Nintendo Switch.
Informations et preuve de concept pour la vulnérabilité de dépassement de tampon basé sur la pile « KartLANPwn » de Mario Kart 8 Deluxe
Écrit par Chad Hyatt
| CVE | CVE-2024-45200 |
| CVSS 3.1 | Non déterminé (Nintendo.. affirme que c'est un 4.3/10) |
| Prime versée | 512 $ |
| Rapport H1 | #2611669 |
| Découverte | 2 juillet 2024 |
| Correction | 11 sept. 2024 (v3.0.3) |
| Divulgation | 29 sept. 2024 |
KartLANPwn est une vulnérabilité dans l'utilisation incorrecte de la bibliothèque réseau P2P Pia par Mario Kart 8 Deluxe, dans laquelle certaines implémentations de « CopyAppData » sont parfois appelées avec un outBufSize plus grand que le tampon out lui-même. Cela peut potentiellement conduire à une exécution de code à distance (RCE) en mode utilisateur sur les consoles des pairs si elle est enchaînée avec une fuite d'informations. KartLANPwn affecte l'utilisation des implémentations de Pia pour le multijoueur LAN/LDN et le multijoueur en ligne NEX.
Cette vulnérabilité affecte toutes les versions de Mario Kart 8 Deluxe jusqu'à la v3.0.1 incluse (v3.0.2 pour la Chine/Tencent), et a spécifiquement été démontrée via la fonctionnalité « LAN Play » de la version commerciale v3.0.1 de MK8DX.
Depuis le 11/09/2024, Nintendo a déployé un correctif pour KartLANPwn avec la v3.0.3 pour toutes les régions, à l'exception de la Chine. Depuis le 27/09/2024, la v3.0.3 a également été publiée pour la Chine. Nous avons divulgué ces informations en toute sécurité après avoir reçu l'autorisation de Nintendo.
La bibliothèque réseau propriétaire Pia est utilisée par les jeux Nintendo Switch first-party prenant en charge le jeu local ou en ligne pour fournir des implémentations de netcode peer-to-peer pour LAN/LDN (multijoueur local) et le protocole NEX, utilisé pour le multijoueur en ligne.
Pour les besoins de la démonstration, nous nous concentrerons spécifiquement sur le protocole LAN de Pia. La console de l'hôte de la salle ouvre une socket UDP de « découverte » sur :30000 à une adresse de diffusion locale (255.255.255.255) et les autres consoles du même réseau sont censées envoyer des « demandes de recherche » depuis leur propre socket (également sur :30000) au routeur pour qu'il les transmette aux autres appareils du même réseau.
L'hôte de la salle (notre « serveur ») renvoie une « réponse à la recherche » initiale censée contenir des informations sur la salle (le nom d'affichage de l'hôte, les données Mii, le nombre de joueurs, etc.). Dans le paquet de réponse à la recherche, la longueur des données d'application à copier dans le tampon out peut être contrôlée avec une valeur allant jusqu'à 150, alors que out ne fait que 128 octets. Cela permet de déborder les valeurs du cadre de pile (dans ce cas précis, pour un pop {r4-r8, pc})
Au moins dans le cas de la version de Pia utilisée par MK8DX, pour ce qui nous intéresse, les paquets de réponse à la recherche pour le LAN sont construits comme suit :
(Tous les types d'entiers sont encodés en big-endian)
| Index | Pseudo-Type | Description |
|---|---|---|
| 0 | u8 | Type de paquet (0x1) |
| 1 | u32 | Taille du corps des informations de session (1266 dans notre cas) |
| 5 | (42 octets) | Champs d'informations de session divers, sans importance pour nous |
| 47 | (0x180 octets) | Début de l'espace pour les données d'application |
| 431 | u32 | Longueur des données d'application |
Le reste des informations de session suit, bien que sans importance pour la construction d'un paquet pour KartLANPwn
LAN_CopyAppData »Pour les besoins de la démonstration, voici un pseudo-code approximatif de l'implémentation LAN de « CopyAppData ». Bien que cette fonction ne présente rien de problématique en soi, une utilisation incorrecte (dans le cas de MK8DX) peut permettre de réécraser le cadre de pile avec nos données d'application d'entrée dans packet.
(fonction située à +0xA0F8C0 dans main pour MK8DX v3.0.1)
void LAN_CopyAppData(int* r0, int packet, int out, uint outBufSize) {
int u1 = 68612;
if (out != NULL) {
// The actual length to read from the `packet` buffer at the start of our
// application data (which our 'server' controls)
uint appDataLength = *(uint *)(packet + 432);
// In some cases, outBufSize is input as a larger number than the bounds of the
// `out` buffer, which allows a stack buffer overflow (in our specific case, `*out`
// is 128 bytes long, and outBufSize is 150!)
if (appDataLength <= outBufSize) {
memcpy(out, packet + 48, outBufSize); // packet[47], start of application data
u1 = 0;
}
*r0 = u1;
return;
}
*r0 = 68615;
return;
}
Voir kartlanpwn-poc.py
Nous avons fourni un simple script de PoC écrit en Python, qui agit comme un faux hôte de salle et répond aux consoles des pairs avec un paquet de « réponse à la recherche » spécialement conçu qui fera planter le processus du jeu lorsque vous ouvrez le menu « LAN Play » dans MK8DX depuis une console sur le même réseau que l'ordinateur exécutant le script.
Soit téléchargez directement le zip du dépôt depuis GitHub, soit clonez-le avec git :
git clone https://github.com/latte-soft/kartlanpwn.git && cd kartlanpwn
python3 kartlanpwn-poc.py
Voir la vidéo de démonstration (YouTube) :
Et pour vous, les passionnés d'ARM, voici une capture d'écran de GDB montrant le segfault du processus résultant :

Il n'a fallu que quelques jours pour comprendre les détails du bug lui-même, mais réussir à exploiter le débordement ? C'est une tout autre paire de manches. Le mode utilisateur du kernel de la Nintendo Switch ne plaisante pas ; il est extrêmement strict dans chaque recoin possible. Nous avons passé de nombreuses heures à échanger et à bidouiller différentes idées et pistes, sans succès final pour une véritable exécution de code (arbitraire). Dans notre cas précis, même un ROP fiable ne semblait pas très réalisable, étant donné que pratiquement toutes les fonctions liées au réseau étaient basées sur des classes, et que nous n'avions aussi qu'un accès en écriture direct à r4-r8. (*_this mon chéri) De plus, sans fuite d'informations préalable, il n'est pas vraiment possible de sauter un mov r4, r0 ou autre pour contrôler le pointeur _this. Amusant, tout ça !
Côté rapport, tout s'est en fait déroulé relativement facilement cette fois-ci avec le triage de Nintendo, du rapport à la divulgation. Bien que la prime de 512 $ ait été bien inférieure à ce que j'avais prévu (ne le sont-elles pas toutes ?), tout vaut mieux que de voir les « Nintendo Ninjas » débarquer à ma porte..
Nintendo a très certainement tiré les leçons des jours plus simples de la Wii, de la 3DS et même de la Wii U. Ils ont fait leurs devoirs ; toute exploitation réussie au-delà d'un crash par déni de service depuis le mode utilisateur sur la Switch est quasi impossible. ASLR, pages No-eXecute forcées (vous ne pouvez pas écrire directement sur des pages mémoire exécutables, les jeux doivent utiliser un sysmodule dédié rien que pour le JIT !), impossibilité de faire du ROP, entre autres points douloureux. (j'attends que la scène du modding me fasse ravaler ces paroles d'ici peu..) D'un autre côté, au cours des derniers mois, j'ai énormément appris sur une plateforme et une architecture complètement nouvelles (pour moi en tout cas) en très peu de temps, sans parler des personnes formidables avec qui j'ai eu le plaisir de travailler sur KartLANPwn ! (Merci Pablo et fishguy 😄)
| Date | Info |
|---|---|
| 2024/07/18 | Rapport soumis à Nintendo via HackerOne |
| 2024/07/31 | Rapport trié en interne |
| 2024/09/11 | Correctif publié avec Mario Kart 8 Deluxe v3.0.3 pour toutes les régions, à l'exception de la Chine |
| 2024/09/12 | Prime versée par Nintendo |
| 2024/09/12 | D'autres chercheurs ont très rapidement découvert le correctif pour « une faille de sécurité dans le netcode du jeu » dans le bindiff de la v3.0.3 |
| 2024/09/27 | Mario Kart 8 Deluxe v3.0.3 publié pour la région chinoise |
| 2024/09/29 | Nintendo a autorisé la divulgation, ce dépôt a été rendu public |
| 2024/09/30 | CVE-2024-45200 publiée par la NVD |
KartLANPwn © 2024 est sous licence CC BY 4.0.
Pour consulter une copie de cette licence, visitez https://creativecommons.org/licenses/by/4.0/