Skip to content
KitploitKITPLOIT
أدواتعمليات الاستغلالالمدونة
Log in
إرسال
أدواتعمليات الاستغلالالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

الخلاصاتاتصالالخصوصية© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2022-3602 — غوص تقني ومضاد لإثبات المفهوم لـ CVE-2022-3602، وهو تجاوز سعة مخزن مؤقت في punycode في OpenSSL 3.0.x، مع سكربتات إعادة الإنتاج وتحليل المكدس وتقييم تخفيف المترجم. | Kitploit
أدوات/GitHubGitHub/colmmacc/cve-2022-3602
تحليل الثغرات الأمنيةالاستغلالالتشفيرتحليل الملفات الثنائيةالأوراق والأبحاثالتعلم والتعليم
GitHubcolmmacc/cve-2022-3602

CVE-2022-3602

غوص تقني ومضاد لإثبات المفهوم لـ CVE-2022-3602، وهو تجاوز سعة مخزن مؤقت في punycode في OpenSSL 3.0.x، مع سكربتات إعادة الإنتاج وتحليل المكدس وتقييم تخفيف المترجم.

عرض المستودع
1693049منذ 3 سنواتتمت المراجعة من قبل Kitploit

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

CVE−2022-3602

ما هذا؟

هذا المستند والمستودع هو توثيق لـ CVE−2022-3602، وهي مشكلة تجاوز سعة المخزن المؤقت (buffer overflow) في ترميز punycode داخل OpenSSL. إنها "مضادّة لإثبات الفكرة" (anti-POC) (يبدو أن المشكلة غير قابلة للاستغلال) مخصصة للأشخاص الذين يحتفظون ببنيات OpenSSL الخاصة بهم ولمطوّري المترجمات (compilers).

هناك CVE منفصلة في نفس الإصدار، وهي CVE-2022-3786، والتي تؤدي أيضًا إلى تجاوزات في سعة المخزن المؤقت، لكن في تلك الحالة لا يمكن للمهاجم التحكم في المحتوى. لا يوجد استنساخ (reproduction) لتلك المشكلة هنا، لكن تلك المشكلة قد تؤدي إلى حرمان من الخدمة (Denial of Service) بسبب الانهيار (crash).

الانهيارات وتجاوزات سعة المخزن المؤقت ليست أمرًا جيدًا أبدًا، وإذا كنت تستخدم OpenSSL 3.0.x، فمن الحكمة التحديث في أقرب وقت ممكن.

لا تتردد في الإبلاغ عن أي أخطاء أو سهو عبر مشاكل GitHub (issues) أو طلبات السحب (pull-requests).

ما هي المشكلة؟

هناك خطأ بمقدار واحد (off-by-one) في طريقة تعامل ossl_punycode_decode مع فك ترميز punycode يؤدي إلى تجاوز سعة بمقدار 4 بايت. لا تكون هذه المشكلة منطقية إلا عندما يعالج OpenSSL سلسلة شهادات، وتتطلب شرطين. أولاً، يجب أن تحتوي شهادة CA أو شهادة وسيطة (Intermediary) في السلسلة على حقل قيد اسم (name-constraint) يستخدم punycode.

nameConstraints = permitted;email:xn-maccrthaigh-n7a.com

ثانيًا، يجب أن تحتوي الشهادة الطرفية (leaf certificate) على حقل otherName من نوع SubjectAlternateName (SAN) يحدد سلسلة SmtpUTF8Mailbox.

otherName = 1.3.6.1.5.5.7.8.9;UTF8:[email protected]

عند التشغيل، سيتم التعامل مع punycode الموجود في حقل nameConstraints، وليس punycode الموجود في حقل otherName، بواسطة محلل punycode الضعيف في OpenSSL.

ما مدى سهولة تشغيل هذه المشكلة؟

حدد David Benjamin و Matt Caswell أن فحص nameConstraint يحدث بعد التحقق العادي من سلسلة الشهادات والتحقق من التوقيع. بالنسبة لمعظم التطبيقات، هذا يعني أنه لا يمكن تشغيل المشكلة بشهادة موقّعة ذاتيًا أو سلسلة غير صالحة.

لاحظ أن تطبيقي s_client و s_server من openssl مخصصان للتصحيح (debugging) ولا يتوقفان عن المعالجة عندما تكون السلسلة غير صالحة.

يجب أن تحتوي شهادة CA أو شهادة وسيطة موثوقة على الحمولة الخبيثة، ويجب أيضًا أن تكون قد وقّعت الشهادة الطرفية التي تشغّل المشكلة.

قد توجد بعض البيئات التي تكون فيها الأطراف غير الموثوقة هي الـ CA أو الوسطاء (Intermediaries)، على سبيل المثال خدمة استضافة تدعم شهادات CA خاصة مقدمة من العملاء، لكن هذا ليس شائعًا.

هل تؤدي المشكلة إلى تنفيذ التعليمات البرمجية عن بُعد (RCE)؟

ستكون الإجابة بالنسبة للعديد من التطبيقات "لا" بسبب كيفية تخطيط المترجم للمكدس (stack) ووجود حمايات أخرى مثل حراس المكدس (stack canaries) / ملفات تعريف الارتباط للمكدس (stack cookies)، والحشو (padding)، وPIE، وFORTIFY_SOURCE.

المشكلة تؤدي بالفعل إلى تجاوز سعة بمقدار 32-بت على المكدس. هذا ليس كافيًا لتنفيذ كود الصدفة (shell code) مباشرة، لكنه قد يكون كافيًا لتغيير تدفق التحكم (control flow) في التطبيق. على سبيل المثال، قد يكون القفز إلى كود صدفة مضمّن في سلسلة شهادات X509 ممكنًا إذا تم أيضًا نسخ هذه البيانات على المكدس في موقع قابل للتنفيذ.

على كل منصة لينكس اختبرتها، يحدث التجاوز في الحشو (padding) ويكون غير ضار. نظريًا، قد يخطّط المترجم المتغيرات بحيث يحدث التجاوز في أحد المتغيرات الأخرى في دالة ossl_a2ulabel.

اعتمادًا على التضمين (inlining)، القائمة الكاملة للمتغيرات الموجودة هي:

outptr, inptr, size, result, tmpptr, delta, seed, utfsize

ولا يبدو لي أن أيًا منها يوفر مسارًا واضحًا لتصعيد الامتيازات (privilege escalation) أو تحكمًا مثيرًا للاهتمام.

لقد أرفقت ملفًا مضغوطًا (tarball) يحتوي على أدوات يمكن استخدامها لإنشاء استنساخات (reproductions) وتجاوزات بأقصى قدر ممكن من التحكم في جميع البايتات الأربعة. سلسلة الاستنساخ المرجعية ( xn--ww90271...aaaa) تتجاوز البايتات الأربعة بالقيم 0xFF 0x0F 0x0F 0x0F. إذا لم يؤدِ ذلك إلى انهيار التطبيق، فمن المحتمل (likely؟) أن هذا التطبيق ليس ضعيفًا (not vulnerable).

كيف يمكنني إعادة إنتاج هذه المشكلة؟

يمكن استخدام النص البرمجي (script) run-poc لإنشاء سلسلة شهادات خبيثة. يتم إنشاء شهادة CA خبيثة من ca.cnf ويتم إنشاء شهادة طرفية محفّزة من leaf.cnf.

تستخدم شهادة CA الحمولة المرجعية التالية:

xn--ww902716aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

يمكن استخدام سكربت بايثون لتوليد سلاسل punycode أخرى لحمولات مختلفة.

عند تنفيذه، سيشغّل run-poc عميلًا وخادمًا من openssl ويحاول استغلال المشكلة عشر مرات.

من المرجح أن ينهار (crash) OpenSSL الضعيف. هذا لا يعني أن إصدار OpenSSL معرّض لـ RCE، لأن حراس المكدس وحمايات ملفات تعريف الارتباط للمكدس تسبب أيضًا عادةً انهيارًا (أكثر أمانًا) للتطبيق. لاحظ أيضًا أن هذا لا يغيّر من شدة الـ CVE الأخرى في نفس الإصدار.

كيف تعمل هذه المشكلة؟

من المدهش أن الحصول على تحكم شبه كامل في جميع البايتات الأربعة للتجاوز يتطلب دقة متناهية، ويتطلب استغلال مفكك ترميز punycode في OpenSSL بترميز punycode غير قياسي / غير صالح. يحتوي الملف المضغوط المرفق على سكربت يمكنه بناء سلسلة تتعامل مع هذه الدقة. فيما يلي شرح لكيفية عملها.

تجهيز المرحلة

المشكلة الأمنية موجودة في ossl_punycode_decode()

int ossl_punycode_decode(const char *pEncoded, const size_t enc_len,
                         unsigned int *pDecoded, unsigned int *pout_length)

يتم استدعاء ossl_punycode_decode من ossl_a2ulabel. مخزن pEncoded هو مخزن بحجم تعسفي إلى حد كبير يأتي من سلسلة شهادات X509. إنه الجزء الذي يأتي بعد أي "xn--" في حقل nameConstraint. راجع [reproduction] لمعرفة كيفية إعادة إنتاج مثل هذه السلسلة من الشهادات.

pDecoded هو مصفوفة من unsigned int بحجم LABEL_BUF_SIZE. LABEL_BUF_SIZE هو 512، وفي معظم المنصات سيكون unsigned int بعرض 4 بايت. لذا في معظم المنصات يكون طول pDecoded هو 2048 بايت.

المشهد

داخل ossl_punycode_decode()، جوهر المشكلة هو فحص الطول غير الصحيح التالي:

 if (written_out > max_out)

max_out يقابل *pout_length وهو دائمًا 512. وwritten_out يتتبع عدد عناصر unsigned int التي تمت كتابتها إلى pDecoded. نظرًا لأنه تتم زيادة written_out لاحقًا فقط بعد الكتابة، فإن هذا الفحص المعيب يسمح بكتابة 513 عنصرًا من unsigned int إلى pDecoded. النتيجة النهائية تبدو شيئًا كهذا ...

pDecoded = [ ... , 'X , 'Y' , 'Z' ] 'P'
// Indices         509   510   511

هنا، وفقًا لاتفاقية لغة C، تكون المؤشرات مفهرسة من الصفر، لذا فإن الفتحة رقم 511 هي العنصر رقم 512 في المصفوفة. 'P' هي حمولة من أربعة بايت تم وضعها خارج الحدود، خارج المساحة المخصصة على المكدس لمخزن buf في ossl_a2ulabel() والذي يشير إليه pDecoded.

أربعة بايت هي تجاوز صغير، ولا تكفي لحمل منزلق nop (nop-sled) أو تنفيذ كود الصدفة مباشرة، لكنها كافية لتغيير تدفق التحكم في التطبيق. على سبيل المثال، قد يكون القفز إلى كود صدفة مضمّن في سلسلة شهادات x509 ممكنًا، اعتمادًا على كيفية تخزين هذه البيانات (أو أجزاء منسوخة من هذه البيانات) وما إذا كانت تلك الذاكرة قابلة للتنفيذ. ومع ذلك، لا تزال هناك صعوبة أكبر أمام المهاجم المحتمل.

أولاً، حشو المترجم ومحاذاة المكدس، أو الدفاعات مثل حراس المكدس (stack canaries)، قد تجعل أي استغلال مستحيلًا تمامًا.

ثانيًا، هناك مسار واحد فقط إلى ossl_punycode_decode()، وهذا المسار يستخدم مخزنًا على المكدس. هذا يجعل من غير المرجح استخدام المشكلة لتجاوزات متزامنة بمقدار 4 بايت في مواقع ذاكرة مختلفة.

فك ترميز Punycode

سلاسل Punycode لها أساسًا شكلان. أحدهما xn--c1yn36f (點看) والآخر xn--maccrthaigh-n7a (maccárthaigh). الجزء الذي يأتي بعد آخر فاصل - هو ترميز bootstring بأساس 36 لأي نقاط رمز يونيكود (unicode code-points) ليست ascii أساسية عادية، مع موضع السلسلة لإدراجها. المهم الآن هو أن عملية فك الترميز في ossl_punycode_decode() تنتج قيمتين. إحداهما 'n' وهي قيمة unsigned int لنقطة الرمز التي سيتم إدراجها، والأخرى 'i' وهي الموضع في المخزن لإدراجها.

يمكن أن تحدث الكتابة بطريقتين مختلفتين. إذا كانت i في مكان ما في منتصف السلسلة، فهناك memmove() التي "تصنع مساحة" أولاً عن طريق نسخ كل شيء إلى اليمين بمقدار فتحة واحدة:

تنزيل الأداة