
Análisis técnico y prueba de concepto para CVE-2024-45200, un desbordamiento de búfer basado en pila en la librería de red Pia P2P de Mario Kart 8 Deluxe, que permite un bloqueo remoto y una potencial ejecución remota de código (RCE) en Nintendo Switch.
Información y prueba de concepto de la vulnerabilidad de desbordamiento de búfer basado en pila "KartLANPwn" de Mario Kart 8 Deluxe
Escrito por Chad Hyatt
| CVE | CVE-2024-45200 |
| CVSS 3.1 | Indeterminado (Nintendo.. afirma que es un 4.3/10) |
| Recompensa pagada | $512 |
| Informe H1 | #2611669 |
| Descubierto | 2 de julio de 2024 |
| Corregido | 11 de septiembre de 2024 (v3.0.3) |
| Divulgado | 29 de septiembre de 2024 |
KartLANPwn es una vulnerabilidad en el uso incorrecto que hace Mario Kart 8 Deluxe de la biblioteca de red P2P Pia, en la que a veces se invoca a implementaciones individuales de "CopyAppData" con un outBufSize mayor que el propio búfer out. Esto puede conducir potencialmente a la ejecución remota de código (RCE) en modo usuario en las consolas de los pares si se encadena con una fuga de información. KartLANPwn afecta al uso de las implementaciones de Pia para el multijugador LAN/LDN y el multijugador online NEX.
Esta vulnerabilidad afecta a todas las versiones de Mario Kart 8 Deluxe hasta la v3.0.1 inclusive (v3.0.2 para China/Tencent), y se ha demostrado específicamente a través de la función "LAN Play" en la versión minorista v3.0.1 de MK8DX.
A partir del 2024/09/11, Nintendo ha desplegado un parche para KartLANPwn junto con la v3.0.3 para todas las regiones, excepto China. A partir del 2024/09/27, la v3.0.3 también se ha publicado para China. Hemos divulgado esta información de forma segura después de recibir permiso de Nintendo.
La biblioteca de red propietaria Pia es utilizada por los juegos de Nintendo Switch de primera parte con soporte para juego local u online para proporcionar implementaciones de netcode peer-to-peer para LAN/LDN (multijugador local) y el protocolo NEX, utilizado para el multijugador online.
Para fines de demostración, nos centraremos específicamente en el protocolo LAN de Pia. La consola del anfitrión de la sala abre un socket UDP de "descubrimiento" en :30000 en una dirección de broadcast local (255.255.255.255) y se supone que otras consolas en la misma red anuncian "solicitudes de exploración" desde su propio socket (también en :30000) al router para que las reenvíe a otros dispositivos en la misma red.
El anfitrión de la sala (nuestro 'servidor') envía de vuelta una "respuesta de exploración" inicial que se supone que contiene información sobre la sala (el nombre visible del anfitrión, los datos de Mii, el nº de jugadores, etc.). Dentro del paquete de respuesta de exploración, la longitud de los datos de aplicación que se copiarán en el búfer out puede controlarse con un valor de hasta 150, aunque out solo tiene 128 bytes de ancho. Esto permite desbordar valores en el marco de pila (en este caso concreto, para un pop {r4-r8, pc})
Al menos en el caso de la versión de Pia que usa MK8DX, para lo que nos ocupa, los paquetes de respuesta de exploración para LAN se construyen de la siguiente manera:
(Todos los tipos int están codificados como big-endian)
| Índice | Pseudo-Tipo | Descripción |
|---|---|---|
| 0 | u8 | Tipo de paquete (0x1) |
| 1 | u32 | Tamaño del cuerpo de la información de sesión (1266 en nuestro caso) |
| 5 | (42 bytes) | Campos diversos de información de sesión, irrelevantes para nosotros |
| 47 | (0x180 bytes) | Inicio del espacio para los datos de aplicación |
| 431 | u32 | Longitud de los datos de aplicación |
El resto de la información de sesión continúa, aunque no es importante para elaborar un paquete para KartLANPwn
LAN_CopyAppData"Con fines de demostración, a continuación se muestra un pseudocódigo aproximado de la implementación LAN de "CopyAppData". Aunque esta función por sí sola no tiene nada inherentemente incorrecto, un uso incorrecto (en el caso de MK8DX) puede permitir que el marco de pila sea sobrescrito por nuestros datos de aplicación de entrada en packet.
(función ubicada en +0xA0F8C0 en main para 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;
}
Hemos proporcionado un sencillo script de PoC escrito en Python, que actúa como un anfitrión de sala falso que responde a las consolas de los pares con un paquete de "respuesta de exploración" especialmente manipulado que bloqueará el proceso del juego cuando abras el menú "LAN Play" en MK8DX desde una consola en la misma red que el ordenador que ejecuta el script.
O bien descarga el zip del repositorio directamente desde GitHub, o clónalo usando git:
git clone https://github.com/latte-soft/kartlanpwn.git && cd kartlanpwn
python3 kartlanpwn-poc.py
Ver demostración en vídeo (YouTube):
Y para los frikis de ARM, aquí tenéis una captura de pantalla de GDB del segfault resultante del proceso:
