
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 :
