
استغلال إثبات المفهوم لـ CVE-2019-0217، حالة سباق في mod_auth_digest لخادم Apache HTTP تسمح بتجاوز المصادقة. يتضمن بيئة ضعيفة قائمة على Docker ونص أتمتة Burp Turbo Intruder.
يحتوي هذا المستودع على إثبات مفهوم لاستغلال CVE-2019-0217، بالإضافة إلى Dockerfile لإعداد خادم ويب معرّض لهذه الثغرة.
في خادم Apache HTTP Server 2.4 الإصدار 2.4.38 والإصدارات السابقة، قد تسمح حالة سباق في mod_auth_digest عند التشغيل على خادم متعدد الخيوط لمستخدم لديه بيانات اعتماد صالحة بالمصادقة باستخدام اسم مستخدم آخر، متجاوزًا قيود التحكم في الوصول المكوّنة.
عندما يحاول عميل الوصول إلى مورد خلف مصادقة HTTP بنمط Digest، يستجيب الخادم برمز الحالة 401، مع ترويسة WWW-Authenticate، بشكل تقريبي بالتنسيق أدناه:
Digest realm="rlm", nonce="TToc8M0jBgA=7afa4f292c97632a6c17eec458d3db31021b111f", algorithm=MD5, qop="auth"
يحسب العميل HA1، وهو ملخص md5 لـ A1 (أي username:realm:password)، ثم يضيف إليه nonce وبيانات وصفية أخرى مثل cnonce للحصول على A2، والذي يعطي ملخص md5 الخاص به بدوره HA2، الذي يرسله العميل كاستجابة، إلى جانب username وcnonce وبيانات وصفية أخرى، في ترويسة Authentication:
'Digest username="attacker", realm="rlm", nonce="TToc8M0jBgA=7afa4f292c97632a6c17eec458d3db31021b111f", uri="/scripts/userprofile.cgi", response="bcb433e4071fa228fe0c9452a7495efd", algorithm="MD5", qop="auth", nc=00000001, cnonce="2309510923095109"
^^^^^^^^^^
كما هو موصوف أدناه، يمكن التلاعب بالجزء المميز من الترويسة أعلاه لإحداث حالة السباق المطلوبة لكي يعمل الاستغلال.
تم إصلاح الثغرة بواسطة هذا الالتزام.
بالنظر إلى كود وحدة mod_auth_digest (تحديدًا دالة get_hash في mod_auth_digest.c)، يتضح أن الخادم يقوم أولاً بتحليل ترويسة Authentication لتحديد ما يقع داخل علامتي الاقتباس بعد username=، وهو ما يعامله كمستخدم مرتبط بالطلب (r->user). ثم يتحقق مما إذا كان هذا "المستخدم" لديه حق الوصول إلى المورد المطلوب أم لا. إذا كان كذلك، تسترجع دالة get_hash قيمة HA1 المقابلة من ملف المصادقة.
قبل التزام إصلاح الثغرة، كانت قيمة HA1 المسترجعة بهذه الطريقة تُخزَّن في المتغير conf = (digest_config_rec *) ap_get_module_config(r->per_dir_config,&auth_digest_module) والذي يبدو أنه ليس آمنًا للخيوط.
وهو ما يمنحنا الاستغلال:
استنادًا إلى قسم تحليل الثغرة أعلاه، ينبغي أن يكون من الممكن إحداث حالة سباق عن طريق إرسال طلبات بترويسة Authentication صالحة في الوقت نفسه مع طلبات بترويسة Authentication مزوّرة (وهي نفس الترويسة الصالحة ولكن مع تعيين قيمة username= إلى المستخدم المستهدف (الذي يريد المهاجم المصادقة باسمه)).
المصطلحات المستخدمة في هذا الاستغلال: - المهاجم (Attacker): المستخدم الذي يشغّل هذا الاستغلال. لديه اسم مستخدم وكلمة مرور صالحان لحسابه الخاص. - الضحية (Victim): المستخدم الذي يريد المهاجم التظاهر بأنه هو. اسم مستخدم الضحية معروف، لكن كلمة المرور (من الواضح) غير معروفة.
تمكنت من جعل هذه الطريقة تعمل عن طريق إغراق عدد من خيوط بايثون (Python threads)، بعضها يرسل طلبات من النوع الأول والبعض الآخر من النوع الثاني، لكنها كانت غير موثوقة وتطلبت عددًا كبيرًا من الطلبات لتنجح. هذا قادني إلى استخدام أداة Turbo Intruder الخاصة بـ Burp (المجانية)، والتي ترسل الطلبات بشكل متوازٍ وموثوق. لسوء الحظ، دعم واجهة الأوامر (CLI) في Turbo Intruder معطوب، لذا يجب تنفيذ بعض أجزاء الاستغلال باستخدام الواجهة الرسومية (GUI).
لاستخدام الخادم المعرّض للثغرة النموذجي الذي أدرجته في هذا المستودع، نفّذ:
$ cd sample_vulnerable_server
$ docker build -t poc_httpd .
$ docker run -p 8038:80 poc_httpd
شغّل generate_turbo_intruder_script.py، بعد تكوين المتغيرات في الأعلى:
# Configuration
URL = 'http://localhost:8038/scripts/userprofile.cgi' # location to the resource protected by digest auth
ATTACKER_USERNAME = 'attacker'
ATTACKER_PASSWORD = 'known'
VICTIM_USERNAME = 'victim'
NUMBER_OF_REQUESTS = 2000 # number of concurrent requests sent to catch a glimpse of the race condition
يقوم هذا البرنامج النصي بعد ذلك بإنشاء ملفين، generated/turbo_intruder_script.py و generated/request.txt، في الدليل الحالي.
الآن افتح BurpSuite Community Edition، وقم بتثبيت إضافة "Turbo Intruder" بالانتقال إلى Extensions -> BApp Store، إذا لم تكن قد فعلت ذلك مسبقًا.
افتح أداة Repeater في Burp. عيّن المضيف والمنفذ للهدف:

الصق محتويات generated/request.txt في قسم الطلب (Request):

انقر بزر الماوس الأيمن في أي مكان في قسم الطلب، واختر 'Extensions->Turbo Intruder->Send to Turbo Intruder'.

الصق محتويات generated/turbo_intruder_script.py في قسم البرنامج النصي:

أخيرًا، انقر على زر Attack في أسفل نافذة Turbo Intruder. يجب أن يعرض أي نتائج ناجحة في الشاشة الناتجة:
