استضاف المنتدى الدولي إيجابي Hack Days 2019 أول مسابقة IDS Bypass. كان على المشاركين فحص شريحة شبكة من خمس عقد ، ثم إما استغلال ثغرة الخدمة ، أو استيفاء شرط محدد (على سبيل المثال ، إرسال استجابة HTTP محددة) وبالتالي الحصول على إشارة. كان العثور على استغلال أمرًا سهلاً ، ولكن IDS تعقد المهمة: كان النظام يقف بين المشاركين والعقد وفحص كل حزمة شبكة. رأى المهاجمون على لوحة القيادة إذا كان التوقيع منع اتصالهم. فيما يلي سوف أخبرك بالتفصيل عن المهام ذاتها وتحليل حلها.
100.64.0.11 - الدعامات
كانت العقدة الأولى في عدد من قاموا بحل المهمة هي الدعامات. بعد مسح منافذ Nmap ، نجد خدمة Apache Struts على المنفذ 8080.

تعرّض عدم حصانة Apache Struts في عام 2017: باستخدام حقن OGNL ، يمكن للمهاجم تنفيذ أي تعليمات برمجية على Struts دون إذن. يوجد استغلال ، على سبيل المثال ، على
GitHub ، ولكن يتم اكتشاف IDS:
[Drop] [**] [1:1001:1] Apache Struts2 OGNL inj in header (CVE-2017-5638) [**]
رمز التوقيع نفسه غير متاح للمشاركين ، ولكن من الرسالة الموجودة في السجلات ، يمكنك فهم آلية عملها. في هذه الحالة ، اكتشف التوقيع حقنة OGNL في HTTP:
GET /showcase.action HTTP/1.1 Accept-Encoding: identity Host: 100.64.0.11:8080 Content-Type: %{(
إذا فحصنا سلوك IDS ، فسيصبح من الواضح أنه يمسك بمجموعة٪ {في بداية رأس Content-Type. هناك العديد من الحلول:
- حاول المشاركempty_jack كسر مجموعة الأحرف٪ {مع قاموسه الخاص للتعبير ، وبالتالي توصل إلى حل باستخدام السطر Content-Type:٪ $ {.
- زغب طلب HTTP نفسه. اكتشف عضو @ c00lhax0r أن الحرف الفارغ في بداية العنوان سيتجاوز أيضًا معرفات: Content-Type: \ 0 $ {.
- معظم مآثر CVE-2017-5638 تقوم بحقن برمز النسبة المئوية. لكن بعض الباحثين في هذا البرنامج ونقاط ضعف Apache Struts السابقة يكتبون أن الحقن يمكن أن يبدأ بـ٪ و $. وبالتالي ، فإن مجموعة $ {ستتجاوز توقيع IDS وتنفذ الكود على النظام. تم اتخاذ هذا القرار في البداية.
كانت هذه المهمة أسهل ، فقد قررها ثمانية مشاركين.
100.64.0.10 - Solr
على المنفذ 8983 كان خادم Apache Solr ، مكتوبًا بلغة جافا.
$ nmap -Pn -sV -p1-10000 100.64.0.10 22/tcp open ssh (protocol 2.0) 8983/tcp open http Jetty

من السهل العثور على استغلال Apache Solr 5.3.0 -
CVE-2019-0192 . يمكن للمهاجم محاكاة ساخرة عنوان خادم RMI في مجموعة. تتطلب العملية إطار عمل yososerial ، الذي يولد سلاسل من كائنات Java (الأدوات) ويوفرها بطرق مختلفة. على سبيل المثال ، من خادم JRMP.
بالطبع ، باستخدام استغلال الجبين في الجبين ، سيرى المشاركون توقيعات IDS تؤدي إلى:
[Drop] [**] [1:10002700:3001] ATTACK [PTsecurity] Java Object Deserialization RCE POP Chain (ysoserial Jdk7u21) [**]
Jdk7u21 هو واحد فقط من ثلاثين تحميلًا ، ويعتمد اختيارهم على المكتبات المستخدمة في الخدمة المستضعفة. تستخدم سلسلة الأدوات Jdk7u21 الفئات القياسية فقط من الإصدار 7u21 من Java Development Kit ، وسلسلة CommonsCollections1 تحتوي على فئات من Apache Common Collections 3.1.
يستبدل المهاجم عنوان خادم RMI في مجموعة Solr بعنوانه الخاص ، ثم يبدأ تشغيل خادم JRMP. يطلب Solr كائنًا في عنوان ويتلقى كائن Java ضارًا. بعد إلغاء تسلسلها ، يتم تنفيذ الكود على الخادم.
وقع التوقيع على سلسلة من الفئات في كائن Java متسلسل. يتم نقله من آلة المهاجم وفي حركة المرور يبدأ مثل هذا:

كان حل هذه المشكلة بسيطًا. يشير التوقيع صراحة إلى Jdk7u21. للالتفاف حوله ، كان عليك تجربة سلاسل أخرى من الأدوات الذكية. على سبيل المثال ، واحدة من العموم. لم تكن هناك تواقيع لسلاسل أخرى في IDS. سيتلقى المشارك قذيفة على النظام وقراءة العلم. أكمل خمسة مشاركين المهمة.
100.64.0.12 - SAMR
واحدة من أصعب المهام في المسابقة. هذا هو جهاز ويندوز مع منفذ 445 مفتوحة. يتم تقسيم العلامة إلى أسماء اثنين من مستخدمي النظام ، ولإكمال المهمة ، كان من الضروري الحصول على قائمة بجميع المستخدمين على عقدة Windows.
بالطبع ، لم يعمل MS17-010 وغيرها من مآثر على هذا الجهاز. يمكن لعدد من المستخدمين ، على سبيل المثال ، البرامج النصية من
Nmap أو إطار عمل
impacket :
$ python samrdump.py 100.64.0.12 Impacket v0.9.15 - Copyright 2002-2016 Core Security Technologies [*] Retrieving endpoint list from 100.64.0.12 [*] Trying protocol 445/SMB… Found domain(s): . SAMR . Builtin [*] Looking up users in domain SAMR [-] The NETBIOS connection with the remote host timed out. [*] No entries received.
كلا السيناريوهات جعل طلبات DCERPC إلى الجهاز على المنفذ 445. ولكن ليس كل شيء بهذه البساطة: يتم حظر بعض الحزم بواسطة IDS ، وهذه المرة يتم تشغيل توقيعين:
[**] [1:2001:2] SAMR DCERPC Bind [**]
[Drop] [**] [1:2002:2] SAMR EnumDomainUsers Request [**]
يكتشف الأول اتصالاً بخدمة SAMR ويقوم بإعلام اتصال TCP بعلامة فقط. ويتم تشغيل الثانية بواسطة طلب EnumDomainUsers لخدمة SAMR. هذه الخدمة لديها طرق أخرى للحصول على المستخدمين: QueryDisplayInfo ، QueryDisplayInfo2 ، QueryDisplayInfo3. تم حظرهم جميعًا بالتوقيعات.
يوفر بروتوكول DCERPC وخدمات Windows فرصًا هائلة لإدارة الموقع البعيد. يتم استخدام هذا البروتوكول بواسطة معظم الأدوات المعروفة ، مثل PsExec أو BloodHound. تسمح لك خدمة SAMR ، أي بروتوكول SAM البعيد ، بالعمل مع الحسابات على المضيف ، بما في ذلك قائمة المستخدمين.
لطلب EnumDomainUsers Impacket بما يلي:

يتم إنشاء اتصال DCERPC بخدمة SAMR عبر SMB ، وتذهب جميع الطلبات الأخرى في سياق هذه الخدمة. تعمل التواقيع على الحزمة الأولى والأخيرة من لقطة الشاشة.
أعطيت اثنين من الأدلة إلى المهمة:
- محاولاتك تؤدي IDS إلى إنشاء 2 تنبيهات. ننظر عن كثب في الأول.
- أي أوامر اتصال لهذا البروتوكول تعرف؟
إنه يتعلق ببروتوكول DCERPC وكيفية إنشاء اتصالات. في قائمة وحدات PDU المتاحة ، يكون أمر Bind و Alter Context مسؤولين عن الاتصال وتغيير السياق ، والثاني يسمح بتغيير السياق الحالي دون انقطاع الاتصال.
لحلها ، كان من الضروري إعادة كتابة منطق البرنامج النصي samrdump:
- يمكنك ربط خدمة أخرى ، على سبيل المثال باستخدام UUID 3919286a-b10c-11d0-9ba8-00c04fd92ef5.
- استخدم Alter Context للتبديل إلى SAMR.
- إرسال طلب إلى EnumDomainUsers.
التغييرات تناسب ثلاثة خطوط:
< dce.bind(samr.MSRPC_UUID_SAMR) --- > dce.bind(uuid.uuidtup_to_bin(("3919286a-b10c-11d0-9ba8-00c04fd92ef5", "0.0"))) > dce.alter_ctx(samr.MSRPC_UUID_SAMR) > dce._ctx = 1
تم اقتراح حل بديل من قبل الفائز بالمسابقة @ psih1337. إرجاع الاستعلام EnumDomainUsers قائمة المستخدمين ليس بالاسم ولكن بواسطة SID (معرف الأمان). سيد ليس رقما عشوائيا. على سبيل المثال ، يحتوي حساب LocalSystem على SID S-1-5-18 ، وبالنسبة للمستخدمين الذين تم إنشاؤها يدويًا ، يبدأ في 1000.
وبالتالي ، فمن خلال فرز البذور يدويًا من 1000 إلى 2000 ، من المحتمل جدًا العثور على الحسابات المطلوبة في النظام. تم العثور عليها تحت sids 1008 و 1009.
يتطلب حل هذه المهمة فهم بروتوكول DCERPC وتجربة البحث في البنى التحتية لـ Windows. كان @ psih1337 هو الشخص الوحيد الذي قرر ذلك.
100.64.0.13 - DNSCAT
على المنفذ 80 توجد صفحة ويب تحتوي على نموذج لعنوان IP.

إذا حددت عنوان IP الخاص بك ، فسيصل UDP إلى المنفذ 53:
17:40:45.501553 IP 100.64.0.13.38730 > 100.64.0.187: 61936+ CNAME? dnscat.d2bc039ce800000000d6eae8eae3bf81fd84d1695f5888aba8dcec06d071.a73b3f0561ca4906d268214f4b70da1bdb50f75739ae0577139096732bf8.0d0a987ce23408bac15426a22e. (173) 17:40:45.501639 IP 100.64.0.187 > 100.64.0.13: ICMP 100.64.0.187 udp port domain unreachable, length 209 17:40:46.520457 IP 100.64.0.13.38730 > 100.64.0.187: 21842+ TXT? dnscat.7f4e039ce800000000d6eae8eae3bf81fd84d1695f5888aba8dcec06d071.a73b3f0561ca4906d268214f4b70da1bdb50f75739ae0577139096732bf8.0d0a987ce23408bac15426a22e. (173) 17:40:46.520546 IP 100.64.0.187 > 100.64.0.13: ICMP 100.64.0.187 udp port domain unreachable, length 209
بوضوح ، هذا هو DNSCAT ، أداة لأنفاق DNS. بعد تحديد عنوان IP في النموذج ، يحاول عميل DNSCAT تأسيس اتصال به. إذا نجح هذا ، فسيحصل الخادم (أي المشارك) على غلاف على الجهاز التنافسي وسحب العلم.
بالطبع ، إذا قمنا برفع خادم DNSCAT وحاولنا قبول الاتصال ، فسوف نفشل:
[Drop] [**] [1:4001:1] 'dnscat' string found in DNS response [**]
يتم تشغيل توقيع IDS على خط dnscat في حركة المرور من خادمنا - وهذا مذكور بوضوح في الرسالة. سوف التعتيم أو تشفير حركة المرور لا تعمل سواء.
بالنظر إلى رمز العميل ، نجد أن الشيكات الموجودة فيه ليست صارمة بما فيه الكفاية. وهذا يعني أن خط dnscat قد لا يظهر على الإطلاق في الاستجابة! يبقى فقط إزالته من التعليمات البرمجية أو استبداله أثناء التنقل باستخدام الأداة المساعدة NetSED. الاستبدال الفوري أسهل بكثير ، لكنني ما زلت سأقدم تصحيحًا لرمز الخادم:
diff -r dnscat2/server/libs/dnser.rb dnscat2_bypass/server/libs/dnser.rb < segments << unpack("a#{len}") > segments << [unpack("a#{len}")[0].upcase] < name.split(/\./).each do |segment| > name.upcase.split(/\./).each do |segment| diff -r dnscat2/server/tunnel_drivers/driver_dns.rb dnscat2_bypass/server/tunnel_drivers/driver_dns.rb < response = (response == "" ? "dnscat" : ("dnscat." + response)) > response = (response == "" ? "dnsCat" : ("dnsCat." + response))
كان هناك خمسة حلول لهذه المهمة في المسابقة.
100.64.0.14 - بعد
لم يتم استلام العلم من مركبة المسابقة هذه من قبل أي شخص.

نرى نموذجًا مألوفًا به عنوان IP. يقدم لنا شخص ما للمشاركة في اختبار برامج ضارة جديدة. من بين ابتكاراتها تجاوز IDS بطريقة غير معروفة. بالنسبة للعلامة ، تحتاج فقط إلى إرسالها رأس HTTP "Server: ng1nx" استجابة. سيكون الجو حارا.
كما هو متوقع: نحصل على طلب GET إلى IP الخاص بنا ونرسل ردًا تم حظره بواسطة IDS.
[Drop] [**] [1:5002:1] 'ng1nx' Server header found. Malware shall not pass [**]
هناك تلميح:
في بعض الأحيان ، تكون المهام التي تبدو صعبة هي أبسطها. إذا كان هناك شيء يبدو ضعيفًا ، فربما تفتقد شيئًا ما تحت أنفك؟
هناك شيء ضعيف أمام أنفنا وهو IDS. من صفحة الاستجابة ، يمكنك أن تجد أن لدينا Suricata IDS مفتوحة.

يؤدي الارتباط الأول في الاستعلام "Suricata IDS Bypass" إلى
CVE-2018-6794 . تسمح مشكلة عدم الحصانة هذه بتجاوز فحص الحزمة في حالة انتهاك المسار العادي لاتصال TCP (مصافحة TCP) وإرسال البيانات قبل اكتمال العملية. يبدو مثل هذا:
Client -> [SYN] [Seq=0 Ack=0] -> Evil Server
قم بتنزيل "استغلال" ، وقم بتغيير السطر إلى "ng1nx" ، وقم بإيقاف تشغيل حزم kernel RST وتشغيلها.
كما ذكرنا سابقًا ، لم يتلق أي شخص الأعلام من هذا الجهاز ، على الرغم من أن اثنين من المشاركين كانا قريبين من الحل.
استنتاج
49 مشاركا مسجلا في المسابقة ، 12 مروا بعلم واحد على الأقل. من المثير للاهتمام أن المهام التنافسية يمكن أن يكون لها عدة حلول في وقت واحد ، لا سيما المهام باستخدام بروتوكول SMB و DCERPC. ربما لديك أفكارك الخاصة لاستكمال بعض المهام؟
الحائز على جائزة الأماكن:
- المركز الأول: @ psih1337
- المركز الثاني: @ webr0ck
- المركز الثالث: @ empty_jack
إحصائيات استجابة التوقيع:

شكرا لجميع المشاركين! في العام القادم سيكون هناك المزيد من المهام بمستويات صعوبة مختلفة.
أرسلت بواسطة كيريل Shipulin ، تقنيات إيجابية