
Informazioni e PoC per CVE-2024-45200, vulnerabilità di buffer overflow "KartLANPwn" di Mario Kart 8 Deluxe
Informazioni e Proof-of-Concept per la vulnerabilità di buffer overflow basato su stack "KartLANPwn" di Mario Kart 8 Deluxe
Scritto da Chad Hyatt
KartLANPwn è una vulnerabilità nell'uso errato della libreria di rete P2P Pia da parte di Mario Kart 8 Deluxe, in cui implementazioni individuali di "CopyAppData" vengono talvolta chiamate con un outBufSize maggiore del buffer out stesso. Questo può portare potenzialmente all'esecuzione remota di codice (RCE) a livello utente sulle console dei peer se abbinato a una fuga di informazioni. KartLANPwn influisce sull'uso delle implementazioni di Pia per il multiplayer LAN/LDN e il multiplayer online NEX.
Questa vulnerabilità colpisce tutte le versioni di Mario Kart 8 Deluxe fino alla v3.0.1 inclusa (v3.0.2 per Cina/Tencent), ed è stata specificamente dimostrata tramite la funzione "LAN Play" sulla versione retail v3.0.1 di MK8DX.
Dal 11/09/2024, Nintendo ha distribuito una correzione per KartLANPwn insieme alla v3.0.3 per tutte le regioni, esclusa la Cina. Dal 27/09/2024, la v3.0.3 è stata rilasciata anche per la Cina. Abbiamo divulgato queste informazioni in sicurezza dopo aver ricevuto il permesso da Nintendo.
La libreria di rete proprietaria Pia è utilizzata dai giochi first-party per Nintendo Switch con supporto multiplayer locale o online per fornire implementazioni netcode peer-to-peer per LAN/LDN (multigiocatore locale) e il protocollo NEX, utilizzato per il multiplayer online.
A scopo dimostrativo, ci concentreremo specificamente sul protocollo LAN di Pia. La console dell'host della stanza apre un socket UDP di "scoperta" su :30000 su un indirizzo broadcast locale (255.255.255.255) e le altre console sulla stessa rete devono pubblicizzare "richieste di navigazione" (browse requests) dal proprio socket (anche su :30000) al router per inoltrarle ad altri dispositivi sulla stessa rete.
L'host della stanza (il nostro 'server') risponde con un pacchetto iniziale di "risposta di navigazione" (browse reply) che dovrebbe contenere informazioni sulla stanza (il nome visualizzato dell'host, dati Mii, numero di giocatori, ecc.). All'interno del pacchetto browse-reply, la lunghezza dei dati dell'applicazione da copiare nel buffer out può essere controllata con un valore fino a 150, anche se out è largo solo 128 byte. Ciò consente di riempire eccessivamente i valori nello stack frame (in questo caso specifico, per un pop {r4-r8, pc})
Almeno nel caso della versione di Pia utilizzata da MK8DX, per ciò su cui ci concentriamo, i pacchetti di risposta di navigazione per LAN sono costruiti come segue:
(Tutti i tipi int sono codificati come big-endian)
Il resto delle informazioni della sessione segue, ma non è importante per creare un pacchetto per KartLANPwn
LAN_CopyAppData"Per scopi dimostrativi, di seguito è riportato uno pseudocodice approssimativo dell'implementazione LAN di "CopyAppData". Sebbene non ci sia nulla di intrinsecamente sbagliato in questa funzione da sola, un uso errato (nel caso di MK8DX) può consentire la sovrascrittura dello stack frame da parte dei nostri dati applicativi in packet.
(funzione situata a +0xA0F8C0 in main per MK8DX v3.0.1)
void LAN_CopyAppData(int* r0, int packet, int out, uint outBufSize) {
int u1 = 68612;
if (out != NULL) {
// La lunghezza effettiva da leggere dal buffer `packet` all'inizio dei nostri
// dati applicativi (che il nostro 'server' controlla)
uint appDataLength = *(uint *)(packet + 432);
// In alcuni casi, outBufSize è inserito come un numero maggiore dei limiti del
// buffer `out`, il che consente un buffer overflow dello stack (nel nostro caso specifico, `*out`
// è lungo 128 byte, e outBufSize è 150!)
if (appDataLength <= outBufSize) {
memcpy(out, packet + 48, outBufSize); // packet[47], inizio dei dati applicativi
u1 = 0;
}
*r0 = u1;
return;
}
*r0 = 68615;
return;
}
Vedi kartlanpwn-poc.py
Abbiamo fornito un semplice script PoC scritto in Python, che agisce come un falso host della stanza che risponde ai peer con un pacchetto "browse-reply" appositamente creato che farà crashare il processo del gioco quando aprirai il menu "LAN Play" in MK8DX da una console sulla stessa rete del computer che esegue lo script.
Scarica il zip del repository direttamente da GitHub, oppure clona usando git:
git clone https://github.com/latte-soft/kartlanpwn.git && cd kartlanpwn
python3 kartlanpwn-poc.py
Vedi la dimostrazione video (YouTube):
E per voi nerd dell'ARM, ecco uno screenshot da GDB del segfault risultante dal processo:

Ci sono voluti solo un paio di giorni per capire i dettagli del bug in sé, ma sfruttare effettivamente l'overflow? Questa è un'altra storia. Il kernel del Nintendo Switch in modalità utente non scherza; è estremamente rigoroso in ogni suo anfratto. Abbiamo passato molte ore scambianoci e manomettendo idee e tracce diverse, senza alcun risultato definitivo per una vera esecuzione di codice (arbitraria). Nel nostro caso specifico, anche un ROP affidabile non sembrava molto fattibile, dato che praticamente tutte le funzioni relative alla rete erano basate su classi, e inoltre avevamo solo accesso diretto in scrittura a r4-r8. (*_this mio adorato) Inoltre, senza una precedente fuga di informazioni, non è molto fattibile saltare un mov r4, r0 o simili per controllare il puntatore _this. Roba divertente!
Dal punto di vista del report, tutto è stato un processo relativamente fluido questa volta con il triage di Nintendo dal momento del report alla divulgazione. Anche se il pagamento della taglia di $512 è stato molto inferiore a quanto previsto (non lo sono tutti?), qualsiasi cosa è meglio che vedere i "Nintendo Ninjas" presentarsi alla mia porta..
Nintendo ha sicuramente imparato la lezione, per così dire, dai tempi più semplici del Wii, 3DS e persino Wii U. Hanno fatto i compiti; lo sfruttamento riuscito di qualsiasi tipo oltre al crash denial-of-service dalla modalità utente su Switch è quasi impossibile. ASLR, pagine No-eXecute forzate (non puoi scrivere direttamente su pagine di memoria eseguibili, i giochi devono usare un sysmodule dedicato solo per JIT!), incapacità di ROP, tra gli altri punti dolenti. (aspettando che la scena del modding si mangi queste parole tra un po'..) D'altra parte, negli ultimi mesi, ho imparato tantissimo su una piattaforma e architettura completamente nuova (per me) in pochissimo tempo, senza dimenticare le persone fantastiche con cui ho avuto il piacere di lavorare su KartLANPwn! (Grazie Pablo e fishguy 😄)
KartLANPwn © 2024 è concesso in licenza sotto CC BY 4.0.
Per visualizzare una copia di questa licenza, visita https://creativecommons.org/licenses/by/4.0/
| Index | Pseudo-Type | Descrizione |
|---|
| 0 | u8 | Tipo di pacchetto (0x1) |
| 1 | u32 | Dimensione del corpo delle informazioni della sessione (1266 nel nostro caso) |
| 5 | (42 bytes) | Campi vari delle informazioni della sessione, irrilevanti per noi |
| 47 | (0x180 bytes) | Inizio dello spazio per i dati dell'applicazione |
| 431 | u32 | Lunghezza dei dati dell'applicazione |
| Date | Info |
|---|
| 2024/07/18 | Report inviato a Nintendo tramite HackerOne |
| 2024/07/31 | Report preso in carico internamente |
| 2024/09/11 | Correzione rilasciata insieme a Mario Kart 8 Deluxe v3.0.3 per tutte le regioni, esclusa la Cina |
| 2024/09/12 | Taglia pagata da Nintendo |
| 2024/09/12 | Altri ricercatori hanno scoperto piuttosto rapidamente la correzione per "a security flaw in the game's netcode" nella bindiff per v3.0.3 |
| 2024/09/27 | Mario Kart 8 Deluxe v3.0.3 rilasciata per la regione cinese |
| 2024/09/29 | Nintendo ha concesso la divulgazione, questo repository reso pubblico |
| 2024/09/30 | CVE-2024-45200 pubblicato dal NVD |