
Informationen und PoC zur ENLBufferPwn-Schwachstelle
| CVE: | CVE-2022-47949 |
| CVSS v3.1: | 9.8/10 (Kritisch) |
| Autoren: | PabloMK7, Rambo6Glaz, Fishguy6564 |
| Gemeldet: | 8. August 2021 (Mario Kart 7) 14. April 2022 (für die betroffenen WiiU- und Switch-Spiele) |
| Offengelegt: | 22. Dezember 2022 |
ENLBufferPwn ist eine Sicherheitslücke im gemeinsamen Netzwerkcode mehrerer Erstanbieter-Nintendo-Spiele seit dem Nintendo 3DS, die es einem Angreifer ermöglicht, durch eine Online-Spielesitzung mit dem Opfer Code aus der Ferne auf der Konsole des Opfers auszuführen (Remote Code Execution). Sie wurde im Laufe des Jahres 2021 von mehreren Personen unabhängig voneinander entdeckt und Nintendo in den Jahren 2021 und 2022 gemeldet. Seit der ersten Meldung hat Nintendo die Sicherheitslücke in vielen betroffenen Spielen behoben. Die Informationen in diesem Repository wurden nach Erhalt der Erlaubnis von Nintendo sicher offengelegt.
Die Sicherheitslücke erreicht eine Bewertung von 9.8/10 (Kritisch) im CVSS-3.1-Rechner.
Hier ist eine Liste von Spielen, von denen bekannt ist, dass sie die Sicherheitslücke zu einem bestimmten Zeitpunkt hatten (alle aufgeführten Switch- und 3DS-Spiele haben Updates erhalten, die die Sicherheitslücke beheben, sodass sie nicht mehr betroffen sind):
Die ENLBufferPwn-Sicherheitslücke nutzt einen Pufferüberlauf in der C++-Klasse NetworkBuffer aus, die in der Netzwerkbibliothek enl (Net in Mario Kart 7) enthalten ist und von vielen Erstanbieter-Nintendo-Spielen verwendet wird. Diese Klasse enthält zwei Methoden, Add und Set, die einen Netzwerkpuffer mit Daten von anderen Spielern füllen. Keine dieser Methoden prüft jedoch, ob die Eingabedaten tatsächlich in den Netzwerkpuffer passen. Da die Eingabedaten kontrollierbar sind, kann ein Pufferüberlauf auf einer entfernten Konsole ausgelöst werden, indem man einfach eine Online-Spielesitzung mit dem Angreifer führt. Wenn es richtig gemacht wird, bemerkt das Opfer möglicherweise nicht einmal, dass eine Sicherheitslücke auf seiner Konsole ausgenutzt wurde. Die Folgen dieses Pufferüberlaufs variieren je nach Spiel, von einfachen, harmlosen Änderungen am Speicher des Spiels (wie dem wiederholten Öffnen und Schließen des Home-Menüs auf dem 3DS) bis hin zu schwerwiegenderen Aktionen wie der vollständigen Übernahme der Konsole, wie unten gezeigt.
Der Rest des Berichts konzentriert sich auf Mario Kart 7, da es aufgrund der fehlenden Sicherheitsmaßnahmen (z. B. ASLR) des 3DS der schwerwiegendste Fall der Sicherheitslücke ist. Es könnte jedoch möglich sein, ASLR bei Switch-Spielen zu umgehen, indem man den NetworkBuffer kapert, der zum Zurücksenden von Daten an den Angreifer verwendet wird (und ihn so dazu bringt, Pointer auf den Heap und Code preiszugeben).
Im folgenden Video wird ein schwerwiegender Fall der Sicherheitslücke in Mario Kart 7 gezeigt, bei dem eine von einem Angreifer kontrollierte Konsole (linke Seite) eine nicht modifizierte Konsole (rechte Seite) vollständig übernimmt. Die einzige Interaktion des Benutzers besteht darin, einer Online-Spielesitzung mit dem Angreifer beizutreten, in diesem Fall über die Funktion „Communities“ (beachte, dass eine „Community“ verwendet wurde, um die Sicherheitslücke sicher und isoliert zu testen und keine anderen Benutzer zu beeinträchtigen, die in öffentlichen Lobbys spielen). Die Übernahme erfolgt durch das Kopieren einer ROP-Payload auf die entfernte Konsole und deren anschließende Ausführung. Diese ROP-Payload nutzt dann weitere Sicherheitslücken im Betriebssystem aus, um Privilegien zu erweitern und die volle Kontrolle zu erlangen. Im Video wird die entfernte Konsole gezwungen, einen CFW-Installer (SafeB9SInstaller) auszuführen. Mit denselben Techniken wäre es theoretisch möglich, Konto- oder Kreditkarteninformationen zu stehlen oder unerlaubte Audio-/Videoaufnahmen mit dem eingebauten Mikrofon/den Kameras der Konsole zu machen.
Wie bereits erwähnt, rührt die Sicherheitslücke von einem Versehen in zwei Methoden der Klasse NetworkBuffer her. Hier ist eine Implementierung der Klasse und der Methoden in C++:
class NetworkBuffer
{
public:
u8 bufferType;
u8* dataPtr;
u32 dataSize;
u32 currentSize;
void Set(u8* newData, u32 newDataSize);
void Add(u8* newData, u32 newDataSize);
}
void NetworkBuffer::Set(u8* newData, u32 newDataSize)
{
memcpy(this->dataPtr, newData, newDataSize);
this->currentSize = newDataSize;
}
void NetworkBuffer::Add(u8* newData, u32 newDataSize)
{
memcpy(this->dataPtr + this->currentSize, newData, newDataSize);
this->currentSize += newDataSize;
}
Wie du sehen kannst, prüfen weder Set noch Add, ob der eingehende newDataSize in die Puffergröße (dataSize) passt. Da diese NetworkBuffer-Klasse als generischer Container zum Austausch von Daten zwischen Spielern online verwendet wird, können der Inhalt von newData und der Wert von newDataSize von einem Angreifer kontrolliert werden, und ein Pufferüberlauf kann durchgeführt werden.
Ein weiteres Detail der Netzwerkbibliothek ist, dass sie asynchron ist, sodass Spiele andere Operationen ausführen können, während Daten in den Puffer gefüllt werden. Um dies zu erreichen, wird eine Doppelpuffer-Technik verwendet. Auf diese Weise kann das Spiel auf bereits empfangene Daten in einem NetworkBuffer zugreifen, während gleichzeitig neue Daten empfangen werden. Nachdem der zweite NetworkBuffer gefüllt ist, werden die Puffer getauscht und der Zyklus wiederholt sich.
Für diesen PoC wird der doppelte NetworkBuffer, der zum Empfangen von Mii-Daten verwendet wird (bufferType = 9), ausgenutzt. Aufgrund der Reihenfolge der Heap-Zuweisung kommt es dazu, dass das NetworkBuffer-Objekt und sein Inhalt nebeneinander platziert werden. Außerdem sind beide Puffer des Doppelpuffers im Speicher zusammenhängend. Das folgende Diagramm zeigt, wie der Speicher nach der Pufferzuweisung aussieht:

Ab jetzt wird der Puffer oben im Bild als Buffer0 bezeichnet, während der Puffer unten Buffer1 ist. Mit diesem Wissen kann ein Angreifer den Pufferüberlauf in Buffer0 auslösen, um die Attribute von Buffer1 zu überschreiben, einschließlich des Members dataPtr. Da 3DS-Spiele kein ASLR implementieren, sind alle Speicherorte in der entfernten Konsole bekannt, sodass dataPtr auf einen beliebigen Ort zeigen kann. Sobald das Spiel die Puffer tauscht, werden die neuen Daten an den beliebigen Ort kopiert. Mit den folgenden Schritten kann eine Payload beliebiger Größe auf die entfernte Konsole kopiert werden:
Buffer0. Sie löst auf der entfernten Konsole einen Überlauf aus, der dataPtr von Buffer1 überschreibt.Buffer1 auf beliebige Daten. Sie werden an die beliebige Adresse kopiert, auf die dataPtr von Buffer1 der entfernten Konsole zeigt.1.Unten ist eine Animation des normalen Betriebs des Spiels zu sehen, gefolgt von der Durchführung der oben beschriebenen Schritte.

Dieses Repository enthält einen PoC, der diese Sicherheitslücke ausnutzt, um je nach Compiler-Flags die folgenden Operationen durchzuführen:
Beachte, dass dieser PoC keine Art von Paketverlusterkennung implementiert, da die Kommunikation zwischen den Konsolen über UDP erfolgt. Um die besten Ergebnisse zu erzielen, sollte eine Behandlung von Paketverlusten im PoC-Code implementiert werden oder die Konsolen sollten sich im selben Netzwerk befinden, um die Wahrscheinlichkeit von Paketverlusten zu verringern.
Eine mögliche Korrektur der anfälligen NetworkBuffer-Klasse ist ebenfalls enthalten.
Die Sicherheitslücke ist auch in der WiiU- und Switch-Version von Mario Kart 8 vorhanden, wurde jedoch nur für die WiiU-Version des Spiels demonstriert.
Während diese Sicherheitslücke von mehreren Benutzern unabhängig voneinander entdeckt wurde, beschlossen viele von ihnen, die Informationen über die Sicherheitslücke privat zu halten. Die folgenden Personen sind jedoch für die sichere Offenlegung der Sicherheitslücke gegenüber Nintendo verantwortlich:
Soweit gesetzlich möglich,
PabloMK7, Rambo6Glaz und Fishguy6564
haben auf alle Urheber- und verwandten Schutzrechte an
ENLBufferPwn verzichtet.
Dieses Werk wird veröffentlicht aus:
Spanien.