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

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

بعد ذلك ، يمكن اعتبار تثبيت اتصال WebSocket مكتملًا. سيتم الآن توفير أي بيانات من كل من العميل والخادم ليس مع http ، ولكن مع رؤوس WebSocket (تبدأ بالبايت 0x82). الآن لا يحتاج الخادم إلى انتظار طلب من العميل لنقل البيانات ، لأن. لم يتم إنهاء اتصال TCP.
هناك العديد من المكتبات في golang للعمل مع مآخذ الويب. الأكثر شعبية منهم والمعيار . سوف نستخدم هذا الأخير ، لأن إنه أبسط وأصغر ويعمل ، كما يقولون ، أسرع قليلاً.
في كود العميل 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 خاص من الشركة . نحتاج إلى فرع مع دعم eSNI (pwu / esni).
نقوم باستنساخه لأنفسنا محليًا أو تنزيل وفك ضغط الرمز البريدي المقابل:
git clone -b pwu/esni https://github.com/cloudflare/tls-tris.gitنحتاج بعد ذلك إلى نسخ دليل GOROOT ، واستبدال الملفات المقابلة من الفرع المستنسخ ، وتعيينه باعتباره الدليل الرئيسي. لإنقاذ المطور من هذا الصداع ، أعد الرجال من CloudFlare نصًا خاصًا - _dev / go.sh. نحن فقط نشغلها. السيناريو مع makefile سيفعل كل شيء بأنفسهم. للفائدة ، يمكنك البحث داخل 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. تقوم الوظيفة الأولى بإنشاء حزمة شبكة مع استعلام إلى خادم CloudFlare DNS باستخدام بروتوكول DoH (DNS-over-HTTPS) ، والثانية تحلل نتائج الاستعلام وتحصل على قيم المفاتيح العامة للمجال ، والثالثة عبارة عن حاوية لأول اثنين.
بعد ذلك ، نضيف إلى وظيفة اتصال مقبس الويب التي تم إنشاؤها حديثًا ConnectForWsSocks وظيفة لطلب مفاتيح eSNI لمجال. عندما يعمل جزء الخادم ، نقوم بتعيين معلمات TLS ، وكذلك تعيين اسم "مجال الغطاء" المزيف:

وتجدر الإشارة هنا إلى أنه في البداية ، لم يتم تصميم فرع tls-tris لاستخدام واجهة المجال. لذلك ، لا يلتفت إلى اسم الخادم المزيف (يتم تمرير حقل اسم الخادم الفارغ كجزء من حزمة الترحيب بالعميل). لإصلاح ذلك ، سيتعين علينا إضافة حقل 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 الخاص بالخادم الافتراضي الخاص الذي استلمناه للتو من مزود الخدمة على القائمة السوداء لهيئة الرقابة المالية الروسية (Roskomnadzor). لذا لا تستغرب إذا حدث لك شيء مشابه. اضطررتُ لاستخدام شبكة افتراضية خاصة (VPN) للوصول إلى خادمي الافتراضي الخاص.
نقوم بنسخ rsockstun الذي تم تجميعه بالفعل إلى VPS (هذا ، بالمناسبة ، هو جمال آخر لـ golang - يمكنك تجميع المشروع بنفسك وتشغيله على أي Linux ، مع ملاحظة شهود النظام فقط) وتشغيل جزء الخادم :

ثم جانب العميل:

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

الآن دعنا نرى ما تراه DPI في قناة الاتصال:

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

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

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

سيتساءل القارئ الفضولي: "ماذا عن العميل في ظل 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 ، على سبيل المثال - المعروف C2 ، أو إجبار CobaltStrike Beacon على استخدام واجهة مجال eSNI عند العمل مع Teamserver عبر ، تم تنفيذه في golang ، أو في C ++ القياسي باستخدام الإصدار المصحح من OpenSSL ، والذي تحدثنا عنه في الجزء الأخير من المقالة. بشكل عام ، لا يوجد حد للخيال.
يتم تقديم مثال مع نفق و CloudFlare في شكل مفهوم ، وحتى الآن من الصعب القول عن الاحتمالات البعيدة لهذا النوع من واجهة المجال. في الوقت الحالي ، لا يتم تنفيذ دعم eSNI إلا بواسطة CloudFlare ، ومن الناحية النظرية ، لا شيء يمنعهم من تعطيل هذا النوع من الواجهة ، على سبيل المثال ، قطع اتصالات tls عندما لا يتطابق SNI و eSNI. بشكل عام ، سيظهر المستقبل. ولكن حتى الآن ، فإن احتمال العمل تحت "غطاء kremlin.ru" يبدو مغريًا للغاية. أليس كذلك؟
يتم وضع كود النفق المحدث ، بالإضافة إلى ملفات exe القابلة للتنفيذ المترجمة في فرع مشروع منفصل على . من الأفضل كتابة مشكلة في صفحة المشروع على GitHub حول جميع مشاكل النفق المحتملة.
المصدر: www.habr.com
