مقدمة
في الجزء الأول من
المقالة ، قدمنا وصفًا موجزًا لآلية SNI (eSNI) المشفرة. أظهروا كيف ، على أساسه ، من الممكن تجنب الكشف عن طريق أنظمة DPI الحديثة (باستخدام Beeline DPI والممنع ILV rutracker كمثال) ، بالإضافة إلى استكشاف إصدار جديد من الواجهة الأمامية للنطاق استنادًا إلى هذه الآلية.
في الجزء الثاني من المقال ، سننتقل إلى المزيد من الأشياء العملية التي ستكون RedTeam مفيدة للمتخصصين في عملهم الصعب. في النهاية ، لا يتمثل هدفنا في الوصول إلى الموارد المحظورة (بالنسبة لهذه الأشياء الشائعة ، لدينا شبكة VPN قديمة جيدة). لحسن الحظ ، يوجد عدد كبير من موفري VPN ، كما يقولون ، لكل ذوق ولون وميزانية.
سنحاول تطبيق آلية واجهة المجال لأدوات RedTeam الحديثة ، على سبيل المثال ، Cobalt Strike ، Empire ، وما إلى ذلك ، ومنحهم فرصًا إضافية لمحاكاة أنظمة فلترة المحتوى الحديثة والتهرب منها.
آخر مرة ، قمنا بتطبيق آلية eSNI في مكتبة OpenSSL واستخدمناها بنجاح في أداة curl المألوفة. لكن حليقة واحدة ، كما يقولون ، لن تكون كاملة. بالطبع ، أرغب في تنفيذ شيء مماثل بلغات عالية المستوى. لكن ، لسوء الحظ ، فإن البحث السريع عن اتساع الشبكة يخيب آمالنا ، لأن دعم آلية eSNI يتم تنفيذه بالكامل في GOLANG فقط. وبالتالي ، فإن خيارنا ليس كبيرًا جدًا: إما أن نكتب بلغة C أو C ++ نقية باستخدام مكتبة OpenSSL المرقعة ، أو نستخدم شوكة GOLANG منفصلة من CloudFlare ونحاول نقل مجموعة الأدوات الخاصة بنا إلى هناك. من حيث المبدأ ، هناك خيار آخر ، أكثر تقليدية ، ولكنه يستغرق وقتًا طويلًا - وهو تنفيذ دعم eSNI للثعبان. بعد كل شيء ، يستخدم Python أيضًا OpenSSL للعمل مع https. لكننا سنترك هذا الخيار للتطوير لشخص آخر ، وسنكتفي بالتطبيق على Golang ، خاصة وأن Cobalt Strike المحبوب لدينا قادر تمامًا على العمل مع قناة اتصال مبنية على أدوات تابعة لجهة خارجية (قناة C2 خارجية) - سنتحدث عن ذلك في نهاية المقال.
جرب Harder ...
من بين الأدوات التي تم تطبيقها على Go هي تطويرنا للدوران داخل الشبكة -
موالف rsockstun ، والذي ، بالمناسبة ، تم اكتشافه الآن بواسطة أدوات Microsoft و Symantec على أنه برنامج ضار للغاية يهدف إلى انتهاك الاستقرار العالمي ...

سيكون من الرائع استخدام التطوير السابق في هذه الحالة. ولكن هنا تنشأ مشكلة صغيرة. الحقيقة هي أن rsockstun يتضمن في البداية استخدام قناة اتصال SSL متزامنة مع الخادم. هذا يعني أنه تم إنشاء الاتصال مرة واحدة وهو موجود طوال مدة تشغيل النفق. وكما تعلم ، فإن بروتوكول https ليس مصممًا لهذا الوضع من التشغيل - إنه يعمل في وضع استجابة الطلب ، حيث يوجد كل طلب http جديد في إطار اتصال tcp جديد.
العيب الرئيسي لهذا المخطط هو أن الخادم لا يمكنه نقل البيانات إلى العميل حتى يرسل العميل طلب http جديد. ولكن لحسن الحظ ، هناك العديد من الخيارات لحل هذه المشكلة - دفق البيانات عبر بروتوكول http (في النهاية ، نتمكن من مشاهدة برامجنا التلفزيونية المفضلة بطريقة أو بأخرى والاستماع إلى الموسيقى من البوابات التي تعمل على https ، ونقل الفيديو والصوت ليس كذلك بخلاف تدفق البيانات). واحدة من التقنيات لمحاكاة تشغيل اتصال tcp كامل عبر بروتوكول http هي تقنية WebSockets ، وجوهرها الرئيسي هو تنظيم اتصال شبكة كامل بين العميل وخادم الويب.
ولحسن حظنا (الصيحة الصاخبة !!!) ، يتم تضمين هذه التكنولوجيا بشكل افتراضي في جميع خطط تعريفة CloudFlare وتعمل بشكل رائع مع eSNI. هذا هو بالضبط ما سوف نستخدمه لتعليم نفقنا لاستخدام واجهات المجال والاختباء من DPI الحديثة.
قليلا عن WebSockets
بادئ ذي بدء ، سوف نخبر باختصار وبكلمات بسيطة عن مآخذ الويب بحيث يكون لدى الجميع فكرة عما سوف نعمل معه.
تسمح لك تقنية مأخذ توصيل الويب بالتبديل مؤقتًا من اتصال http إلى بيانات التدفق القياسية عبر مقبس الشبكة دون قطع اتصال tcp الثابت. عندما يريد العميل التبديل إلى مقبس ويب ، يقوم بتعيين عدة رؤوس http في طلب http الخاص به.
العنوانان المطلوبان هما
الاتصال: ترقية وترقية: websocket . يمكن أن يفرض أيضًا إصدار بروتوكول websocket (
Sec-Websockset-Version: 13 ) وشيء مثل معرف مقبس ويب base64 (
Sec-WebSocket-Key: DAGDJSiREI3 + KjDfwxm1FA == ). يستجيب الخادم من خلال http-code 101 Switching Protocols ويقوم أيضًا بتعيين رؤوس
الاتصال والترقية و
Sec-WebSocket-Accept . عملية التحويل موضحة في لقطة الشاشة أدناه:

بعد ذلك ، يمكن اعتبار اتصال WebSocket مكتمل. سيتم الآن تزويد أي بيانات من كل من العميل والخادم ليس بـ http ، ولكن مع رؤوس WebSocket (تبدأ بالبايت 0x82). الآن لا يحتاج الخادم إلى انتظار طلب من العميل من أجل نقل البيانات ، مثل لم يتم كسر اتصال TCP.
هناك العديد من المكتبات في عصابة مأخذ التوصيل على شبكة الإنترنت. الأكثر شعبية من هذه هي
Gorilla WebSocket و
WebSocket القياسية. سوف نستخدم هذا الأخير ، لأنه إنه أبسط وأصغر ويعمل ، كما يقولون ، أسرع قليلاً.
في رمز عميل rsockstun ، نحتاج إلى استبدال مكالمات net.dial أو tls.dial بمكالمات WebSocket المقابلة:


نريد أن نجعل العميل جزءًا من النفق لدينا عالميًا وقادر على العمل من خلال اتصال ssl مباشر وعبر بروتوكول WebSockset. للقيام بذلك ، سنقوم بإنشاء خطأ في وظيفة منفصلة
func connectForWsSocks (سلسلة العنوان ، سلسلة الوكيل) {...} عن طريق القياس مع
connectForSocks () وسنستخدمه للعمل مع مآخذ الويب إذا كان عنوان الخادم المحدد عند بدء تشغيل العميل سيبدأ بـ ws: أو wss: (في حالة Secure WebSocket).
بالنسبة لجانب الخادم من النفق ، سنقوم أيضًا بإنشاء وظيفة منفصلة للعمل مع مآخذ الويب. سيتم إنشاء مثيل لفئة http وسيتم تعيين معالج اتصال HTTP (وظيفة wsHandler):

وسنضع كل منطق معالجة الاتصال (تخويل العميل بكلمة مرور وتثبيت وإنهاء جلسة yamux) في معالج اتصال WebSocket:

نحن نجمع المشروع ، نبدأ جزء الخادم:
./rsockstun –listen ws:127.0.0.1:8080 –pass P@ssw0rd
ثم الجزء العميل:
./rsockstun -connect ws:127.0.0.1:8080 –pass P@ssw0rd
ونحن نتحقق من العمل على المضيف المحلي:


نمر إلى واجهة المجال
يبدو أننا قمنا بتسوية مآخذ الويب. الآن دعنا نذهب مباشرة إلى eSNI وواجهات المجال. كما ذكرنا سابقًا ، للعمل مع DoH و eSNI ، نحتاج إلى اتخاذ فرع خاص من golang من
CloudFlare . نحن بحاجة إلى فرع بدعم eSNI (pwu / esni).
نقوم باستنساخها لأنفسنا محليًا أو نقوم بتنزيل الرمز البريدي المقابل وتوسيعه:
git clone -b pwu/esni https://github.com/cloudflare/tls-tris.git
ثم نحتاج إلى نسخ دليل GOROOT واستبدال الملفات المقابلة من الفرع المستنسخ وتعيينه على أنه الرئيسي. لإنقاذ المطور من هذا الصداع ، أعد الرجال من CloudFlare برنامج نصي خاص - _dev / go.sh. مجرد تشغيله. النصي جنبا إلى جنب مع makefile سوف تفعل كل شيء بأنفسهم. للمتعة - يمكنك البحث داخل ملف التعريف للحصول على التفاصيل.
بعد إعداد البرنامج النصي ، عند تجميع المشروع ، سنحتاج إلى الإشارة إلى GOROOT كدليل محلي تم إعداده بواسطة البرنامج النصي. في حالتنا ، يبدو كما يلي:
GOROOT="/opt/tls-tris/_dev/GOROOT/linux_amd64" go build ….
بعد ذلك ، نحتاج إلى تنفيذ وظائف طلب وتحليل مفاتيح eSNI العامة للمجال المطلوب في النفق. في حالتنا ، ستكون هذه مفاتيح eSNI عامة من خوادم CloudFlare الأمامية. للقيام بذلك ، سنقوم بإنشاء ثلاث وظائف:
func makeDoTQuery(dnsName string) ([]byte, error) func parseTXTResponse(buf []byte, wantName string) (string, error) func QueryESNIKeysForHost(hostname string) ([]byte, error)
أسماء الوظائف ، من حيث المبدأ ، تتحدث عن نفسها. سنأخذ الملف من ملف esni_query.go ، وهو جزء من tls-tris. تقوم الوظيفة الأولى بإنشاء حزمة شبكة مع طلب إلى خادم DNS CloudFlare باستخدام بروتوكول DoH (DNS-over-HTTPS) ، والثانية تقوم بتوزيع نتائج الاستعلام وتتلقى قيم مفاتيح المجال العام ، والثالثة عبارة عن حاوية للأولين.
بعد ذلك ،
نقدم وظيفة طلب مفاتيح eSNI للمجال في وظيفة الاتصال التي تم إنشاؤها حديثًا من أجل
connectForWsSocks مأخذ الويب. عندما يعمل جزء الخادم ، اضبط معلمات TLS ، وقم أيضًا بتعيين اسم "مجال التغطية" المزيف:

تجدر الإشارة هنا إلى أنه في البداية ، لم يتم تصميم فرع tls-tris لاستخدام واجهة المجال. لذلك ، لا ينتبه إلى الاسم المزيف للخادم (يتم إرسال حقل serverName فارغ كجزء من حزمة hello-client). لإصلاح هذا الأمر ، سيتعين علينا إضافة حقل FakeServerName المقابل إلى بنية TlsConfig. لا يمكننا استخدام حقل ServerName القياسي للبنية ، لأن يتم استخدامه بواسطة آليات tls الداخلية وإذا كان يختلف عن الأصل ، فإن مصافحة tls ستنتهي بخطأ ما. ويرد وصف بنية TlsConfig في
ملف tls / common.go - يتعين علينا إصلاحه:


بالإضافة إلى ذلك ، سيتعين علينا إجراء تغييرات على ملف
tls / handshake_client.go لاستخدام حقل FakeServerName الخاص بنا عند إنشاء مصافحة TLS:

هذا كل شئ! يمكنك ترجمة المشروع والتحقق من العمل. ولكن قبل إجراء الاختبار ، يجب عليك تكوين حساب CloudFlare الخاص بك. حسنًا ، كيف يمكنك إعداد - قم فقط بإنشاء حساب cloudflare واربط نطاقك به. يتم تضمين جميع الرقائق المتعلقة بـ DoH و WebSocket و ESNI في CloudFlare بشكل افتراضي. بعد تحديث سجلات DNS - يمكنك التحقق من المجال عن طريق تشغيل طلب مفتاح eSNI:
dig +short txt _esni.df13tester.info

إذا رأيت شيئًا مماثلاً لنطاقك ، فكل شيء يناسبك ويمكنك متابعة الاختبار.
قم بتشغيل Ubuntu VPS ، على سبيل المثال ، على DigitalOcean. ملاحظة: في حالتنا ، كان عنوان IP الخاص بـ VPS الذي أصدره المزود للتو في قائمة ILV السوداء. لذلك لا تتفاجأ إذا حدث شيء مشابه لك. اضطررت لاستخدام VPN للوصول إلى VPS الخاص بي.
نحن ننسخ rsockstun المترجمة إلى VPS (هذا ، بالمناسبة ، هو سحر آخر من golang - يمكنك تجميع المشروع بنفسك وتشغيله على أي نظام Linux ، مع ملاحظة سعة بت النظام فقط) وبدء تشغيل جزء الخادم:

ثم الجزء العميل:

كما نرى ، قام العميل بالاتصال بالخادم بنجاح من خلال خادم CloudFlare للجهة الأمامية باستخدام مقبس ويب. للتحقق من أن النفق يعمل تمامًا مثل النفق ، يمكنك تقديم طلب حليقة من خلال الجوارب المحلية 5 المفتوحة على الخادم:

الآن دعونا نرى ما تراه إدارة شؤون الإعلام في قناة الاتصال:

أولاً ، يقوم موالف النفق ، باستخدام آلية DoH ، بالوصول إلى خادم Cloudflare DNS لمفاتيح eSNI للمجال الوجهة (الحزم رقم 1-19) ، ثم الوصول إلى الخادم الأمامي وإنشاء اتصال TLS ، والاختباء تحت النطاق
www.google.com (هذه القيمة) بشكل افتراضي ، عندما لا يتم تعيين مجال مزيف عند بدء تشغيل العميل). لتحديد مجالك المزيف ، يجب عليك استخدام المعلمة -fronfDomain:


الآن شيء واحد آخر. بشكل افتراضي ، يتم ضبط إعدادات حساب CloudFalre على SSL المرنة. هذا يعني أنه سيتم إعادة توجيه طلبات https إلى خوادم الواجهة الأمامية من Cloudflare من العملاء في نموذج (http) غير مشفر إلى خادمنا. هذا هو السبب في أننا أطلقنا جزء الخادم من النفق في وضع غير ssl (-listen ws: 0.0.0.0) ، وليس (-listen wss: 0.0.0.0).

للتبديل إلى وضع التشفير الكامل ، يجب عليك تحديد
كامل أو
كامل (صارم) في حالة وجود هذه الشهادة على الخادم. بعد تبديل الوضع ، سنكون قادرين على قبول الاتصالات من CloudFlare عبر بروتوكول https. تذكر إنشاء شهادة موقعة ذاتيا لجانب الخادم من النفق.

سوف يسأل قارئ مزعج: "ماذا عن حساب العميل تحت ويندوز؟ في الواقع ، بالتأكيد ، فإن التطبيق الرئيسي للنفق هو رفع الاتصال الخلفي من أجهزة الشركات والخوادم ، وهناك ، كقاعدة عامة ، هو نظام Windows دائمًا. كيف يمكنني تجميع نفق لنظام Windows ، وحتى باستخدام مكدس TLS محدد؟ "والآن ، سنقدم شريحة أخرى توضح مدى ملاءمة golang. نحن نجمع النوافذ مباشرة من كالي ، ببساطة عن طريق إضافة معلمة GOOS = windows:
GOARCH=amd64 GOROOT="/opt/tls-tris/_dev/GOROOT/linux_amd64" GOOS=windows go build -ldflags="-s -w"
أو خيار 32 بت:
GOARCH=386 GOROOT="/opt/tls-tris/_dev/GOROOT/linux_amd64" GOOS=windows go build -ldflags="-s -w"
هذا كل شئ! وليس هناك حاجة لمزيد من المشاكل. انها حقا تعمل!

يلزم وجود علامات برنامج التحويل البرمجي –w و –s من أجل إزالة البيانات المهملة الزائدة من الملف القابل للتنفيذ ، مما يجعله أقل بمقدار بضع ميغا بايت. بالإضافة إلى ذلك ، يمكن بعد ذلك تعبئتها باستخدام UPX لتقليل حجمها.
بدلا من الاستنتاج
في هذه المقالة ، باستخدام مثال لموالف مكتوب على golang ، أظهرنا بوضوح استخدام التكنولوجيا الجديدة لواجهة المجال ، والتي تم تنفيذها على ميزة مثيرة للاهتمام إلى حد ما في بروتوكول TLS 1.3. وبالمثل ، يمكنك تكييف مجموعة الأدوات الموجودة المكتوبة على golang لتعمل من خلال خادم CloudFlare ، على سبيل المثال
Merlin أو C2 المشهور أو إجبار CobaltStrike Beacon على استخدام واجهات مجال eSNI عند العمل مع Teamserver عبر
قناة C2 الخارجية ، والتي يتم تنفيذها على golang القياسية النسخة المصححة من OpenSSL ، والتي تحدثنا عنها في الجزء الأخير من المقال. بشكل عام ، الخيال ليس له حدود.
يتم تقديم مثال النفق و CloudFlare في شكل مفهوم ولا يزال من الصعب القول عن الاحتمالات البعيدة لهذا النوع من المواجهة بين المجال. في الوقت الحالي ، يتوفر دعم eSNI فقط في CloudFlare ، ومن حيث المبدأ ، لا يوجد ما يمنعهم من تعطيل هذا النوع من الواجهة الأمامية ، على سبيل المثال ، قطع اتصال tls عندما لا يتطابق SNI و eSNI. بشكل عام ، فإن المستقبل تظهر. لكن في الوقت الحالي ، يبدو احتمال العمل تحت غطاء kremlin.ru جذابًا للغاية. أليس كذلك؟
توجد رمز النفق المحدّث ، وكذلك ملفات exe القابلة للتنفيذ المترجمة ، في فرع مشروع منفصل على
جيثب . من الأفضل أن تكتب مشكلة حول جميع مشاكل النفق المحتملة على صفحة المشروع على جيثب.