
Information and PoC about the ENLBufferPwn vulnerability
| CVE: | CVE-2022-47949 |
| CVSS v3.1: | 9.8/10 (Critical) |
| 작성자: | PabloMK7, Rambo6Glaz, Fishguy6564 |
| 보고일: | 2021년 8월 8일 (Mario Kart 7) 2022년 4월 14일 (영향을 받은 WiiU 및 Switch 게임 대상) |
| 공개일: | 2022년 12월 22일 |
ENLBufferPwn은 Nintendo 3DS 이후 출시된 여러 퍼스트 파티 Nintendo 게임의 공통 네트워크 코드에서 발견된 취약점으로, 공격자가 피해자와 온라인 게임을 하는 것만으로 피해자의 콘솔에서 원격으로 코드를 실행할 수 있게 합니다(원격 코드 실행). 이 취약점은 2021년에 여러 사람이 독립적으로 발견했으며, 2021년과 2022년에 걸쳐 Nintendo에 보고되었습니다. 최초 보고 이후 Nintendo는 여러 취약한 게임에서 이 취약점을 패치했습니다. 이 저장소의 정보는 Nintendo의 허가를 받은 후 안전하게 공개되었습니다.
이 취약점은 CVSS 3.1 계산기에서 9.8/10 (Critical) 점수를 받았습니다.
다음은 한때 이 취약점이 존재했던 것으로 알려진 게임 목록입니다(목록에 있는 모든 Switch 및 3DS 게임은 이 취약점을 패치하는 업데이트를 받았으므로 더 이상 영향을 받지 않습니다):
ENLBufferPwn 취약점은 많은 퍼스트 파티 Nintendo 게임에서 사용되는 네트워크 라이브러리 enl(Mario Kart 7에서는 Net)에 존재하는 C++ 클래스 NetworkBuffer의 버퍼 오버플로를 악용합니다. 이 클래스에는 다른 플레이어로부터 오는 데이터로 네트워크 버퍼를 채우는 두 가지 메서드 Add와 Set가 있습니다. 그러나 이 두 메서드 모두 입력 데이터가 실제로 네트워크 버퍼에 맞는지 확인하지 않습니다. 입력 데이터는 공격자가 제어할 수 있으므로, 공격자와 온라인 게임 세션을 하는 것만으로 원격 콘솔에서 버퍼 오버플로를 트리거할 수 있습니다. 제대로 수행되면 피해자는 자신의 콘솔에서 취약점이 트리거되었다는 사실조차 인지하지 못할 수 있습니다. 이 버퍼 오버플로의 결과는 게임에 따라 다양하며, 게임 메모리에 대한 단순하고 무해한 수정(3DS에서 홈 메뉴를 반복적으로 열고 닫는 것과 같은)부터 아래에서 볼 수 있듯이 콘솔을 완전히 제어하는 것과 같은 더 심각한 동작까지 다양합니다.
이 보고서의 나머지 부분은 Mario Kart 7에 초점을 맞출 것입니다. 3DS에는 보안 조치(예: ASLR)가 부족하기 때문에 Mario Kart 7이 이 취약점의 가장 심각한 사례입니다. 그러나 Switch 게임에서는 공격자에게 데이터를 다시 보내는 데 사용되는 NetworkBuffer를 하이재킹하여(힙과 코드에 대한 포인터를 누출시키도록 만들어) ASLR을 우회하는 것이 가능할 수도 있습니다.
다음 비디오는 Mario Kart 7에서 이 취약점의 심각한 사례를 보여줍니다. 공격자가 제어하는 콘솔(왼쪽)이 수정되지 않은 콘솔(오른쪽)을 완전히 장악합니다. 사용자가 수행하는 유일한 상호작용은 공격자와 온라인 게임 세션에 참여하는 것입니다. 이 경우 "communities" 기능을 사용했습니다(공개 로비에서 플레이하는 다른 사용자에게 영향을 주지 않고 취약점을 격리된 방식으로 안전하게 테스트하기 위해 "community"를 사용했다는 점에 유의하세요). 장악은 ROP 페이로드를 원격 콘솔에 복사한 다음 실행하는 방식으로 수행됩니다. 이 ROP 페이로드는 이후 OS의 다른 취약점을 사용하여 권한을 상승시키고 완전한 제어권을 얻습니다. 비디오에서 원격 콘솔은 CFW 설치 프로그램(SafeB9SInstaller)을 실행하도록 강제됩니다. 동일한 기술을 사용하면 이론적으로 계정/신용카드 정보를 도용하거나 콘솔에 내장된 마이크/카메라를 사용하여 허가 없이 오디오/비디오를 녹화하는 것이 가능할 수 있습니다.
앞서 언급했듯이, 이 취약점은 NetworkBuffer 클래스의 두 메서드에 존재하는 실수에서 비롯됩니다. 다음은 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;
}
보시다시피 Set과 Add 모두 들어오는 newDataSize가 버퍼 크기(dataSize)에 맞는지 확인하지 않습니다. 이 NetworkBuffer 클래스는 온라인 플레이어 간에 데이터를 교환하기 위한 범용 컨테이너로 사용되므로, newData의 내용과 newDataSize의 값은 공격자가 제어할 수 있으며 버퍼 오버플로를 수행할 수 있습니다.
네트워크 라이브러리의 또 다른 세부 사항은 비동기식이라는 점입니다. 따라서 데이터가 버퍼에 채워지는 동안 게임은 다른 작업을 수행할 수 있습니다. 이를 위해 이중 버퍼 기법이 사용됩니다. 이렇게 하면 게임은 새 데이터가 수신되는 동시에 NetworkBuffer에 이미 수신된 데이터에 접근할 수 있습니다. 두 번째 NetworkBuffer가 채워지면 버퍼가 교체되고 주기가 반복됩니다.
이 PoC에서는 Mii 데이터(bufferType = 9)를 수신하는 데 사용되는 이중 NetworkBuffer가 악용될 것입니다. 힙 할당 순서로 인해 NetworkBuffer 객체와 그 내용물이 서로 인접하게 배치됩니다. 또한 이중 버퍼의 두 버퍼는 메모리에서 연속적입니다. 다음 다이어그램은 버퍼 할당 후 메모리의 모습을 나타냅니다:

이제부터 이미지 상단의 버퍼는 Buffer0, 하단의 버퍼는 Buffer1로 지칭됩니다. 이러한 정보를 바탕으로 공격자는 Buffer0에서 버퍼 오버플로를 트리거하여 dataPtr 멤버를 포함한 Buffer1의 속성을 덮어쓸 수 있습니다. 3DS 게임은 ASLR을 구현하지 않으므로 원격 콘솔의 모든 메모리 위치가 알려져 있어 dataPtr을 임의의 위치를 가리키도록 설정할 수 있습니다. 게임이 버퍼를 교체하면 새 데이터가 임의의 위치에 복사됩니다. 다음 단계를 수행하면 어떤 크기의 페이로드든 원격 콘솔에 복사할 수 있습니다:
Buffer0에 전송합니다. 그러면 원격 콘솔에서 오버플로가 트리거되어 Buffer1의 dataPtr이 덮어써집니다.Buffer1의 내용을 임의의 데이터로 설정합니다. 해당 데이터는 원격 콘솔의 Buffer1 dataPtr이 가리키는 임의의 주소에 복사됩니다.1부터 다시 시작합니다.아래는 게임의 정상 작동 애니메이션과 그다음 위에서 설명한 단계를 수행하는 모습입니다.

이 저장소에는 컴파일러 플래그에 따라 다음 작업을 수행하는, 이 취약점을 악용하는 PoC가 포함되어 있습니다:
콘솔 간 통신은 UDP를 사용하여 이루어지므로 이 PoC는 어떤 종류의 패킷 손실 감지도 구현하지 않는다는 점을 유의하세요. 최상의 결과를 얻으려면 PoC 코드에 패킷 손실 처리를 구현하거나, 콘솔을 동일한 네트워크에 배치하여 패킷 손실 가능성을 줄여야 합니다.
취약한 NetworkBuffer 클래스에 대한 가능한 수정 사항도 제공됩니다.
이 취약점은 Mario Kart 8의 WiiU 및 Switch 버전에도 존재하지만, WiiU 버전의 게임에서만 시연되었습니다.
이 취약점은 여러 사용자가 독립적으로 발견했지만, 그중 많은 사용자가 취약점 정보를 비공개로 유지하기로 결정했습니다. 그러나 다음 사람들이 이 취약점을 Nintendo에 안전하게 공개하는 역할을 담당했습니다:
법이 허용하는 범위 내에서,
PabloMK7, Rambo6Glaz and Fishguy6564
는 ENLBufferPwn에 대한 모든 저작권 및 관련/인접 권리를 포기했습니다.
이 저작물은 다음 국가에서 발행되었습니다:
스페인.