
معلومات وإثبات المفهوم حول ثغرة ENLBufferPwn
| CVE: | CVE-2022-47949 |
| CVSS v3.1: | 9.8/10 (حرجة) |
| المؤلفون: | PabloMK7, Rambo6Glaz, Fishguy6564 |
| أُبلغ عنه: | 8 أغسطس 2021 (Mario Kart 7) 14 أبريل 2022 (بالنسبة لألعاب WiiU وSwitch المتأثرة) |
| تم الإفصاح عنه: | 22 ديسمبر 2022 |
ENLBufferPwn هي ثغرة في كود الشبكة المشترك للعديد من ألعاب نينتندو الحصرية منذ عهد نينتندو 3DS، وتسمح للمهاجم بتنفيذ كود عن بُعد على جهاز الضحية بمجرد خوض مباراة عبر الإنترنت معه (تنفيذ كود عن بُعد). اكتُشفت من قِبل عدة أشخاص بشكل مستقل خلال عام 2021، وأُبلغت إلى نينتندو خلال عامي 2021 و2022. ومنذ التقرير الأولي، أصدرت نينتندو تصحيحات لهذه الثغرة في العديد من الألعاب المتأثرة. تم الكشف عن المعلومات الواردة في هذا المستودع بأمان بعد الحصول على إذن من نينتندو.
حصلت الثغرة على درجة 9.8/10 (حرجة) في حاسبة CVSS 3.1.
فيما يلي قائمة بالألعاب التي من المعروف أنها تأثرت بالثغرة في وقت ما (جميع ألعاب Switch و3DS المذكورة تلقت تحديثات أصلحت الثغرة، لذا لم تعد متأثرة):
تستغل ثغرة ENLBufferPwn مشكلة تجاوز سعة المخزن المؤقت في صنف C++ المسمى NetworkBuffer الموجود في مكتبة الشبكة enl (Net في Mario Kart 7)، والتي تستخدمها العديد من ألعاب نينتندو الحصرية. يحتوي هذا الصنف على طريقتين Add وSet تملآن مخزنًا شبكيًا ببيانات قادمة من لاعبين آخرين. ومع ذلك، لا تتحقق أي من هاتين الطريقتين من أن بيانات الإدخال تناسب فعليًا المخزن المؤقت للشبكة. وبما أن بيانات الإدخال قابلة للتحكم، يمكن تحفيز تجاوز سعة المخزن المؤقت على جهاز بعيد بمجرد بدء جلسة لعب عبر الإنترنت مع المهاجم. وإذا نُفذ ذلك بشكل صحيح، فقد لا يلاحظ المستخدم الضحية حتى أن ثغرة قد استُغلت على جهازه. تختلف عواقب تجاوز سعة المخزن المؤقت هذا حسب اللعبة، بدءًا من تعديلات بسيطة وغير ضارة على ذاكرة اللعبة (مثل فتح قائمة الرئيسية على 3DS وإغلاقها مرارًا) وصولًا إلى إجراءات أكثر خطورة مثل السيطرة الكاملة على الجهاز، كما هو موضح أدناه.
سيركز بقية التقرير على Mario Kart 7، نظرًا لافتقار جهاز 3DS إلى إجراءات أمنية (مثل ASLR)، فهو الحالة الأشد خطورة لهذه الثغرة. ومع ذلك، قد يكون من الممكن تجاوز ASLR في ألعاب Switch من خلال اختطاف NetworkBuffer المستخدم لإرسال البيانات مرة أخرى إلى المهاجم (وجعله يسرّب مؤشرات إلى heap والكود).
يعرض الفيديو التالي حالة خطيرة من الثغرة في Mario Kart 7، حيث يسيطر جهاز يتحكم به مهاجم (الجانب الأيسر) سيطرة كاملة على جهاز غير معدّل (الجانب الأيمن). التفاعل الوحيد الذي قام به المستخدم هو الانضمام إلى جلسة لعب عبر الإنترنت مع المهاجم، وفي هذه الحالة باستخدام ميزة "المجتمعات" (لاحظ أنه تم استخدام "مجتمع" لاختبار الثغرة بأمان بطريقة معزولة وعدم التأثير على أي مستخدمين آخرين يلعبون في صالات عامة). تتم السيطرة عبر نسخ حمولة ROP إلى الجهاز البعيد ثم تنفيذها. تستخدم حمولة ROP هذه بعد ذلك ثغرات أخرى في نظام التشغيل لرفع الامتيازات والحصول على تحكم كامل. في الفيديو، يُجبر الجهاز البعيد على تشغيل مثبّت 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، وبالتالي يمكن تنفيذ تجاوز سعة المخزن المؤقت.
من التفاصيل الأخرى لمكتبة الشبكة أنها غير متزامنة (asynchronous)، بحيث يمكن للألعاب القيام بعمليات أخرى أثناء امتلاء المخزن المؤقت بالبيانات. ولتحقيق ذلك، تُستخدم تقنية المخازن المزدوجة. بهذه الطريقة، يمكن للعبة الوصول إلى البيانات المستلمة بالفعل في NetworkBuffer في نفس الوقت الذي تُستقبل فيه بيانات جديدة. بعد امتلاء NetworkBuffer الثاني، يتم تبادل المخازن وتتكرر الدورة.
في هذا الـ PoC، سيتم استغلال NetworkBuffer المزدوج المستخدم لاستقبال بيانات Mii (bufferType = 9). نظرًا لترتيب تخصيص heap، يحدث أن كائن NetworkBuffer ومحتوياته يكونان متجاورين. أيضًا، كلا المخزنين في المخزن المزدوج متجاوران في الذاكرة. يوضح المخطط التالي شكل الذاكرة بعد تخصيص المخزن:

من الآن فصاعدًا، سيُشار إلى المخزن أعلى الصورة باسم Buffer0، بينما المخزن أسفلها باسم Buffer1. باستخدام هذه المعرفة، يمكن للمهاجم تحفيز تجاوز سعة المخزن المؤقت في Buffer0 للكتابة فوق سمات Buffer1، بما في ذلك العضو dataPtr. نظرًا لأن ألعاب 3DS لا تطبق ASLR، فإن جميع مواقع الذاكرة في الجهاز البعيد معروفة، لذا يمكن توجيه dataPtr إلى أي موقع مرغوب. بمجرد أن تتبادل اللعبة المخازن، سيتم نسخ البيانات الجديدة إلى ذلك الموقع. بتنفيذ الخطوات التالية، يمكن نسخ حمولة بأي حجم إلى الجهاز البعيد:
Buffer0. سيؤدي ذلك إلى تحفيز تجاوز سعة في الجهاز البعيد، مع الكتابة فوق dataPtr الخاص بـ Buffer1.Buffer1 ببيانات اعتباطية. سيتم نسخها إلى العنوان الاعتباطي المشار إليه بواسطة dataPtr الخاص بـ Buffer1 في الجهاز البعيد.1.يوجد أدناه رسم متحرك للتشغيل العادي للعبة، يليه تنفيذ الخطوات الموضحة أعلاه.

يحتوي هذا المستودع على PoC يستغل هذه الثغرة لتنفيذ العمليات التالية، اعتمادًا على خيارات المترجم (compiler flags):
ضع في اعتبارك أن هذا الـ PoC لا يطبق أي نوع من كشف فقدان الحزم، حيث تتم الاتصالات بين الأجهزة عبر UDP. للحصول على أفضل النتائج، يجب تنفيذ معالجة فقدان الحزم في كود الـ PoC أو وضع الأجهزة على نفس الشبكة لتقليل فرص فقدان الحزم.
كما تم توفير إصلاح محتمل لصنف NetworkBuffer الثغري هنا.
توجد الثغرة أيضًا في نسختي WiiU وSwitch من Mario Kart 8، ولكن تم توضيحها فقط لإصدار WiiU من اللعبة.
بينما اكتُشفت هذه الثغرة من قبل عدة مستخدمين بشكل مستقل، قرر كثير منهم إبقاء معلومات الثغرة خاصة. ومع ذلك، فإن الأشخاص التاليين هم المسؤولون عن الكشف الآمن عن الثغرة لشركة نينتندو:
إلى أقصى حد يسمح به القانون،
PabloMK7, Rambo6Glaz وFishguy6564
تنازلوا عن جميع حقوق النشر والحقوق ذات الصلة أو المجاورة الخاصة بـ
ENLBufferPwn.
يُنشر هذا العمل من:
إسبانيا.