
Informações e PoC para CVE-2024-45200, a vulnerabilidade de estouro de buffer "KartLANPwn" do Mario Kart 8 Deluxe
Informação e Prova de Conceito para a vulnerabilidade de estouro de buffer baseado em pilha "KartLANPwn" do Mario Kart 8 Deluxe
Escrito por Chad Hyatt
KartLANPwn é uma vulnerabilidade no uso incorreto da biblioteca de rede P2P Pia do Mario Kart 8 Deluxe, na qual implementações individuais de "CopyAppData" são às vezes chamadas com um outBufSize maior que o próprio buffer out. Isso pode potencialmente levar à execução remota de código (RCE) em modo de usuário nos consoles dos pares se combinado com um vazamento de informações. KartLANPwn afeta o uso das implementações de LAN/LDN multijogador local e NEX multijogador online da Pia.
Esta vulnerabilidade afeta todas as versões do Mario Kart 8 Deluxe até e incluindo v3.0.1 (v3.0.2 para China/Tencent), e foi especificamente demonstrada através do recurso "LAN Play" na versão de varejo v3.0.1 do MK8DX.
A partir de 2024/09/11, a Nintendo implantou uma correção para KartLANPwn junto com v3.0.3 para todas as regiões, excluindo a China. A partir de 2024/09/27, v3.0.3 foi agora também lançada para a China. Divulgamos de forma segura estas informações após receber permissão da Nintendo.
A biblioteca de rede proprietária Pia é usada por jogos first-party do Nintendo Switch com suporte local ou online para fornecer implementações de netcode ponto a ponto para LAN/LDN (multijogador local) e o protocolo NEX, usado para multijogador online.
Para fins de demonstração, focaremos especificamente no protocolo LAN da Pia. O console anfitrião da sala abre um socket UDP de "descoberta" em :30000 em um endereço de broadcast local (255.255.255.255) e outros consoles na mesma rede devem anunciar "solicitações de busca" a partir do seu próprio socket (também em :30000) para o roteador encaminhar para outros dispositivos na mesma rede.
O anfitrião da sala (nosso 'servidor') envia de volta uma "resposta de busca" inicial que deve conter informações sobre a sala (nome de exibição do anfitrião, dados Mii, número de jogadores, etc.). Dentro do pacote de resposta de busca, o comprimento dos dados da aplicação a serem copiados para o buffer out pode ser controlado com um valor de até 150, embora out tenha apenas 128 bytes de largura. Isso permite transbordar valores no quadro de pilha (neste caso específico, para um pop {r4-r8, pc})
Pelo menos no caso da versão do Pia que o MK8DX está usando, no que estamos focando, os pacotes de resposta de busca para LAN são construídos da seguinte forma:
(Todos os tipos int são codificados como big-endian)
O resto das informações da sessão continua, embora não sejam importantes para criar um pacote para o KartLANPwn
LAN_CopyAppData"Para fins de demonstração, abaixo está um pseudocódigo aproximado da implementação LAN de "CopyAppData". Embora nada esteja inerentemente errado com esta função sozinha, o uso incorreto (no caso do MK8DX) pode permitir que o quadro de pilha seja sobrescrito pelos nossos dados de aplicação de entrada no packet.
(função localizada em @ +0xA0F8C0 no 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;
}
Veja kartlanpwn-poc.py
Fornecemos um script PoC simples escrito em Python, que atua como um anfitrião de sala falso que responde aos consoles dos pares com um pacote de "resposta de busca" especialmente criado que irá travar o processo do jogo quando você abrir o menu "LAN Play" no MK8DX a partir de um console na mesma rede que o computador executando o script.
Baixe o zip do repositório diretamente do GitHub ou clone usando git:
git clone https://github.com/latte-soft/kartlanpwn.git && cd kartlanpwn
python3 kartlanpwn-poc.py
Veja a demonstração em vídeo (YouTube):
E para vocês, nerds de ARM, aqui está uma captura de tela do GDB do segfault resultante do processo:

Levou apenas alguns dias para descobrir os detalhes do bug em si, mas realmente fazer uso do transbordamento? Isso é uma lata de minhocas completamente diferente. O modo de usuário do kernel do Nintendo Switch não brinca; é extremamente rigoroso em cada fenda que pode ser. Passamos muitas horas trocando e adulterando diferentes ideias e pistas, sem sucesso final para execução real (arbitrária) de código. No nosso caso específico, até mesmo ROP confiável não parecia muito viável, já que praticamente todas as funções relacionadas à rede eram baseadas em classes, além de termos apenas acesso de escrita direta a r4-r8. (*_this meu querido) Além disso, sem um vazamento de informação anterior, não é muito viável apenas pular um mov r4, r0 ou algo assim para controlar o ponteiro _this. Coisa divertida!
Do lado do relatório, tudo foi um processo relativamente tranquilo desta vez com a triagem da Nintendo, desde o relatório até a divulgação. Embora o pagamento da recompensa de $512 tenha sido muito menor do que eu esperava (não são todos?), qualquer coisa é melhor do que os "Nintendo Ninjas" aparecendo na minha porta.
A Nintendo definitivamente aprendeu a lição, por assim dizer, desde os dias mais simples do Wii, 3DS e até do Wii U. Eles fizeram o dever de casa; a exploração bem-sucedida de qualquer tipo além de travamento por negação de serviço a partir do modo de usuário no Switch é quase impossível. ASLR, páginas No-eXecute forçadas (você não pode escrever diretamente em páginas de memória executáveis, os jogos precisam usar um sysmodule dedicado apenas para JIT!), incapacidade de fazer ROP, entre outros pontos de dor. (esperando a cena de modding engolir essas palavras daqui a pouco..) Por outro lado, nos últimos meses, aprendi muito sobre uma plataforma e arquitetura completamente novas (para mim, de qualquer forma) em um tempo muito curto, sem mencionar as pessoas incríveis com quem tive o prazer de trabalhar no KartLANPwn! (Obrigado, Pablo e fishguy 😄)
KartLANPwn © 2024 está licenciado sob CC BY 4.0.
Para ver uma cópia desta licença, visite https://creativecommons.org/licenses/by/4.0/
| Índice | Tipo-Pseudo | Descrição |
|---|
| 0 | u8 | Tipo de pacote (0x1) |
| 1 | u32 | Tamanho do corpo de informações da sessão (1266 no nosso caso) |
| 5 | (42 bytes) | Campos diversos de informações da sessão, irrelevantes para nós |
| 47 | (0x180 bytes) | Início do espaço para dados da aplicação |
| 431 | u32 | Comprimento dos dados da aplicação |
| Data | Informação |
|---|
| 2024/07/18 | Relatório submetido à Nintendo via HackerOne |
| 2024/07/31 | Relatório triado internamente |
| 2024/09/11 | Correção lançada junto com Mario Kart 8 Deluxe v3.0.3 para todas as regiões, excluindo a China |
| 2024/09/12 | Recompensa paga pela Nintendo |
| 2024/09/12 | Outros pesquisadores rapidamente descobriram a correção para "uma falha de segurança no netcode do jogo" na bindiff para v3.0.3 |
| 2024/09/27 | Mario Kart 8 Deluxe v3.0.3 lançado para a região chinesa |
| 2024/09/29 | Nintendo concedeu divulgação, este repositório tornado público |
| 2024/09/30 | CVE-2024-45200 publicado pelo NVD |