وكيل عكسي لـ C2 من Cobalt Strike يصد الفرق الزرقاء ومضادات الفيروسات وأنظمة EDR والماسحات من خلال فحص الحزم وارتباط Malleable Profile
(المعروف سابقًا باسم إضافة proxy2's malleable_redirector)
دعونا نرفع مستوى مرونة موجهات C2 أمام فرق الاستجابة للحوادث، أليس كذلك؟

شهد مجال فرق الاختراق الأحمر عدة أفكار رائعة حول كيفية مواجهة فرق الاستجابة للحوادث وتضليلهم مع تقديم شبكة موجهات C2 مقاومة في نفس الوقت.
يجمع هذا العمل العديد من تلك الأفكار الرائعة في أداة واحدة خفيفة الوزن، تحاكي Apache2 في جوهرها كخادم وكيل عكسي بسيط HTTP(S).
من خلال الجمع بين فهم ملفات تعريف Malleable C2، ومعرفة تجمعات عناوين IP الضارة، ومرونة إضافة منطق فحص وتوجيه خاطئ جديد بسهولة - نتج عن ذلك طارد ماهر لعمليات فحص فرق الاستجابة للحوادث.

إذا وصلت أي حزمة واردة غير صالحة إلى RedWarden - يمكنك redirect (إعادة توجيه)، أو reset (إعادة تعيين)، أو مجرد proxy (وكيل) بعيدًا!
يعمل هذا البرنامج كخادم وكيل عكسي HTTP/HTTPS مع عدة قيود مفروضة على طلبات C2 HTTP الواردة، حيث يختار أي الحزم يجب توجيهها إلى Teamserver وأيها يجب إسقاطها، على غرار قيود ملف .htaccess المفروضة في Apache2's mod_rewrite.
تم إنشاء RedWarden لحل مشكلة تجنب IR/AV/EDRs/Sandboxes في طبقة موجه C2. وهو يهدف إلى استبدال الإعدادات التقليدية لـ Apache2 + mod_rewrite المستخدمة لهذا الغرض.
الميزات:
يأخذ RedWarden ملف تعريف C2 Malleable و hostname:port الخاص بـ Teamserver كمدخلات. ثم يقوم بتحليل أقسام ملف التعريف المقدمة لفهم العقد وتمرير فقط تلك الطلبات الواردة التي تفي به مع توجيه الآخرين بشكل خاطئ.
يتم استخدام أقسام مثل http-stager و http-get و http-post و URIs المقابلة لها، والرؤوس، وأنماط prepend/append، و User-Agent كلها للتمييز بين طلب Beacon الشرعي والضوضاء غير المرتبطة بالإنترنت أو الحزم الخارجة عن نطاق IR/AV/EDRs.
يستفيد البرنامج من نطاقات IP السيئة المعروفة الرائعة القادمة من: curi0usJack وآخرون: https://gist.github.com/curi0usJack/971385e8334e189d93a6cb4671238b10
باستخدام القائمة السوداء لعناوين IP إلى جانب البحث عن الكلمات المفتاحية السيئة المعروفة من خلال استعلامات Reverse-IP DNS وفحص رؤوس HTTP، يوفر ذلك موثوقية لزيادة مرونة الموجه أمام النظائر غير المصرح لهم الذين يرغبون في فحص بنى المهاجمين التحتية.
يمكن توجيه الحزم غير الصالحة بشكل خاطئ وفقًا لثلاث استراتيجيات:
يتم فرض هذا التكوين في ملف التكوين:```yaml
drop_action: redirect
المثال أدناه يظهر نتيجة `redirect` إلى `https://googole.com`:

استخدم بحكمة، كن آمنًا.
### المتطلبات
يمكن لهذا البرنامج العمل فقط على أنظمة لينكس لأنه يستخدم fork لإنشاء عمليات متعددة.
أيضًا، من المتوقع أن يكون الأمر النظامي `openssl` مثبتًا لأنه يُستخدم لإنشاء شهادات SSL.
أخيرًا، قم بتثبيت جميع متطلبات Python3 PIP بسهولة باستخدام:```shell
bash $ sudo pip3 install -r requirements.txt
قد يحتوي ملف التكوين config.yaml الخاص بـ RedWarden على:```yaml port:
profile: jquery-c2.3.14.profile
ssl_cacert: /etc/letsencrypt/live/attacker.com/fullchain.pem ssl_cakey: /etc/letsencrypt/live/attacker.com/privkey.pem
teamserver_url:
drop_action: reset
ثم، يمكن تشغيل البرنامج عن طريق إعطائه مسارًا لملف التكوين:```shell
bash$ sudo python3 RedWarden.py -c config.yaml
[INFO] 19:21:42: Loading 1 plugin...
[INFO] 19:21:42: Plugin "malleable_redirector" has been installed.
[INFO] 19:21:42: Preparing SSL certificates and keys for https traffic interception...
[INFO] 19:21:42: Using provided CA key file: ca-cert/ca.key
[INFO] 19:21:42: Using provided CA certificate file: ca-cert/ca.crt
[INFO] 19:21:42: Using provided Certificate key: ca-cert/cert.key
[INFO] 19:21:42: Serving http proxy on: 0.0.0.0, port: 80...
[INFO] 19:21:42: Serving https proxy on: 0.0.0.0, port: 443...
[INFO] 19:21:42: [REQUEST] GET /jquery-3.3.1.min.js
[INFO] 19:21:42: == Valid malleable http-get request inbound.
[INFO] 19:21:42: Plugin redirected request from [code.jquery.com] to [1.2.3.4:8080]
[INFO] 19:21:42: [RESPONSE] HTTP 200 OK, length: 5543
[INFO] 19:21:45: [REQUEST] GET /jquery-3.3.1.min.js
[INFO] 19:21:45: == Valid malleable http-get request inbound.
[INFO] 19:21:45: Plugin redirected request from [code.jquery.com] to [1.2.3.4:8080]
[INFO] 19:21:45: [RESPONSE] HTTP 200 OK, length: 5543
[INFO] 19:21:46: [REQUEST] GET /
[...]
[ERROR] 19:24:46: [DROP, reason:1] inbound User-Agent differs from the one defined in C2 profile.
[...]
[INFO] 19:24:46: [RESPONSE] HTTP 301 Moved Permanently, length: 212
[INFO] 19:24:48: [REQUEST] GET /jquery-3.3.1.min.js
[INFO] 19:24:48: == Valid malleable http-get request inbound.
[INFO] 19:24:48: Plugin redirected request from [code.jquery.com] to [1.2.3.4:8080]
[...]
يحتوي الإخراج أعلاه على سطر يشير إلى وجود طلب وارد غير مصرح به، وغير متوافق مع ملف تعريف C2 الخاص بنا، وقد تم إسقاطه بسبب سلسلة User-Agent غير متوافقة المقدمة:``` [...] [DROP, reason:1] inbound User-Agent differs from the one defined in C2 profile. [...]
## حالات الاستخدام
### فرض تحديد الموقع الجغرافي للـ IP على مصادر حركة المرور الخاصة بـ Beacon
لقد قمت بعمل Pre-Phish و OSINT بشكل جيد للغاية. أنت تعرف الآن أين يعيش أهدافك ولديك بعض الأدلة حول من أين يجب أن تنشأ حركة المرور، أو على الأقل كيفية اكتشاف حركة المرور الإضافية تمامًا.
كيف تفرض تحديد الموقع الجغرافي للـ IP على طلبات Beacon على redirector؟
RedWarden يأتي للمساعدة!
لنفترض أنك تريد فقط قبول حركة المرور القادمة من بولندا، أوروبا.
نتائج Pre-Phish/OSINT الخاصة بك تشير إلى أن:
- `89.64.64.150` هو عنوان IP شرعي لأحد أهدافك، قادم من بولندا
- `59.99.140.76` بينما هذا ليس كذلك وقد وصل إلى أنظمتك كحزمة ضوضاء إنترنت عادية.
يمكنك استخدام أداة RedWarden المساعدة `lib/ipLookupHelper.py` لجمع بيانات التعريف الجغرافية للـ IP حول هذين العنوانين:
> `python3 lib/ipLookupHelper.py -i 89.64.64.150`
>
> :::```shell
bash$ python3 ipLookupHelper.py
Usage: ./ipLookupHelper.py <ipaddress> [malleable-redirector-config]
Use this small utility to collect IP Lookup details on your target IPv4 address and verify whether
your 'ip_geolocation_requirements' section of proxy2 malleable-redirector-config.yaml would match that
IP address. If second param is not given - no
الأول يجلب:```shell bash$ python3 ipLookupHelper.py 89.64.64.150 [dbg] Following IP Lookup providers will be used: ['ip_api_com', 'ipapi_co'] [.] Lookup of: 89.64.64.150 [dbg] Calling IP Lookup provider: ipapi_co [dbg] Calling IP Lookup provider: ip_api_com [dbg] New IP lookup entry cached: 89.64.64.150 [.] Output: { "organization": [ "UPC Polska Sp. z o.o.", "UPC.pl", "AS6830 Liberty Global B.V." ], "continent": "Europe", "continent_code": "EU", "country": "Poland", "country_code": "PL", "ip": "89.64.64.150", "city": "Warsaw", "timezone": "Europe/Warsaw", "fulldata": { "status": "success", "country": "Poland", "countryCode": "PL", "region": "14", "regionName": "Mazovia", "city": "Warsaw", "zip": "00-202", "lat": 52.2484, "lon": 21.0026, "timezone": "Europe/Warsaw", "isp": "UPC.pl", "org": "UPC Polska Sp. z o.o.", "as": "AS6830 Liberty Global B.V.", "query": "89.64.64.150" }, "reverse_ip": "89-64-64-150.dynamic.chello.pl" }
والأخير يعطي:```shell
bash$ python3 ipLookupHelper.py 59.99.140.76
[dbg] Following IP Lookup providers will be used: ['ip_api_com', 'ipapi_co']
[dbg] Read 1 cached entries from file.
[.] Lookup of: 59.99.140.76
[dbg] Calling IP Lookup provider: ip_api_com
[dbg] New IP lookup entry cached: 59.99.140.76
[.] Output:
{
"organization": [
"",
"BSNL Internet",
"AS9829 National Internet Backbone"
],
"continent": "Asia",
"continent_code": "AS",
"country": "India",
"country_code": "IN",
"ip": "59.99.140.76",
"city": "Palakkad",
"timezone": "Asia/Kolkata",
"fulldata": {
"status": "success",
"country": "India",
"countryCode": "IN",
"region": "KL",
"regionName": "Kerala",
"city": "Palakkad",
"zip": "678001",
"lat": 10.7739,
"lon": 76.6487,
"timezone": "Asia/Kolkata",
"isp": "BSNL Internet",
"org": "",
"as": "AS9829 National Internet Backbone",
"query": "59.99.140.76"
},
"reverse_ip": ""
}
الآن ترى أن الأول كان يحتوي على "country": "Poland" بينما الثاني يحتوي على "country": "India". بهذه المعرفة، نحن مستعدون لصياغة قيودنا في شكل قاموس YAML ضخم:```yaml
ip_geolocation_requirements:
organization:
continent:
continent_code:
country:
- Poland
- PL
- Polska
country_code:
city:
timezone:
كل إدخال في ذلك القاموس يقبل تعبيرًا منتظمًا يتم مطابقته مع البيانات الوصفية الجغرافية (IP Geo) المحددة لعنوان IP الخاص بالند الوارد.
نستخدم ثلاثة إدخالات في الخاصية `country` للسماح بالطلبات التي تحتوي على إحدى القيم المحددة.
بعد تعيين ذلك في التهيئة الخاصة بك، يمكنك التحقق مما إذا كان عنوان IP آخر سيتم تمريره عبر مُحدد الموقع الجغرافي لـ RedWarden أم لا باستخدام أداة `ipLookupHelper` التي تقبل معاملًا ثانيًا:

يخبرك السطر الأخير جدًا ما إذا كانت الحزمة سيتم حظرها أو قبولها.
وهذا كل شيء! قم بتكوين قيود الموقع الجغرافي IP بحكمة وأمان، وافحص بعناية سجلات RedWarden لأي إدخالات DROP متعلقة بالموقع الجغرافي IP، وحافظ على حركة C2 الخاصة بك نظيفة ومرتبة!
### إصلاح طلبات Beacon المعدلة
إذا كنت تستخدم أنظمة وسيطة مثل AWS Lambda أو CloudFlare كموجهات نطاق أمامي / معيدات توجيه، فمن المؤكد أنك واجهت موقفًا حيث لم يتمكن بعض حزمك من قبولها من قبل Teamserver لأنها انحرفت عن العقد القابل للتشكيل (malleable contract) المتفق عليه. سواء كان رأس HTTP معدل أو محذوف، أو إعادة ترتيب الكوكيز أو أي شيء آخر - أراهن أن ذلك أضاع ساعات كثيرة من حياتك.
لمكافحة مشاكل عملية إعداد قنوات C2 والتلاعب بالأنظمة الوسيطة، تقدم RedWarden وظيفة لإصلاح حزم Beacon.
تفعل ذلك عن طريق التحقق مما يتوقعه الملف الشخصي القابل للتشكيل (Malleable Profile) من الحزمة، ويمكنها استعادة رؤوس HTTP المكونة إلى قيمها المتفق عليها وفقًا لمتطلبات الملف الشخصي.
ضع في اعتبارك الملف الشخصي البسيط التالي:```
http-get {
set uri "/api/abc";
client {
header "Accept-Encoding" "gzip, deflate";
metadata {
base64url;
netbios;
base64url;
parameter "auth";
}
}
...
هل ترى هذا Accept-Encoding؟ يجب أن يأتي كل طلب Beacon مع هذا الرأس وهذه القيمة. ماذا يحدث إذا اصطدم Beacon الخاص بك بأنظمة CloudFlare وأصدرت طلبًا سيتم تجريده من هذا الرأس أو سيكون لديه Accept-Encoding: gzip بدلاً من ذلك؟ سيقوم Teamserver بإسقاط الطلب فورًا.
من خلال تعيين هذا الرأس في قسم تكوين RedWarden المسمى repair_these_headers يمكنك تأمين اتصالك.:```yaml
repair_these_headers:
### إزالة رؤوس الاستجابة الإشكالية
مع Cobalt Strike 4.7+ لاحظت أن Teamserver يزيل رأس `Content-Encoding` تلقائياً دون أي إشعار، مما ينتهك عقدنا `http-(get|post).server` القابل للتخصيص.
نظراً لأن RedWarden اتبعت العقد، كان Beacon إما يتجاهل الاستجابات أو يفك ضغطها بشكل غير صحيح.
يحدد هذا الخيار الرؤوس القادمة من استجابات Teamserver التي يجب إزالتها قبل الوصول إلى عملية Beacon:```yaml
remove_these_response_headers:
- Content-Encoding
RedWarden ستقوم الآن بإزالة رأس Content-Encoding افتراضيًا من استجابات Teamserver، للحفاظ على التوافق مع إصدارات CS4.7+.
لنلقي نظرة على المخرجات التي ينتجها الوكيل.
تحت خيار verbose: True، سيتم ضبط مستوى التفصيل على INFO على الأكثر لإخبار الطلبات المقبولة من المرفوضة.
قد يتم قبول الطلب إذا استوفى جميع المعايير المكونة في ملف تهيئة RedWarden. ستتبع هذه الحالة إدخال سجل [ALLOW, ...]:```
[INFO] 2021-04-24/17:30:48: [REQUEST] GET /js/scripts.js
[INFO] 2021-04-24/17:30:48: == Valid malleable http-get (variant: default) request inbound.
[INFO] 2021-04-24/17:30:48: [ALLOW, 2021-04-24/19:30:48, 111.222.223.224] "/js/scripts.js" - UA: "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
[INFO] 2021-04-24/17:30:48: Connected peer sent 2 valid http-get and 0 valid http-post requests so far, out of 15/5 required to consider him temporarily trusted
[INFO] 2021-04-24/17:30:48: Plugin redirected request from [attacker.com] to [127.0.0.1:5555]
إذا فشل الطلب في أي من الفحوصات التي يجريها RedWarden على كل طلب، فسيتم إصدار السطر المقابل `[DROP, ...]` الذي يحتوي على معلومات حول سبب الإسقاط **السبب**.:```
[INFO] 2021-04-24/16:48:28: [REQUEST] GET /
[ERROR] 2021-04-24/16:48:29: [DROP, 2021-04-24/18:48:28, reason:1, 128.14.211.186] inbound User-Agent differs from the one defined in C2 profile.
[INFO] 2021-04-24/16:48:29: [DROP, 2021-04-24/18:48:28, 128.14.211.186] "/" - UA: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
[ERROR] 2021-04-24/16:48:29: [REDIRECTING invalid request from 128.14.211.186 (zl-dal-us-gp3-wk107.internet-census.org)] GET /
هناك العديد من الأسباب التي تحدد ما إذا كان يمكن إسقاط الطلب. يمكن تشغيل أو إيقاف كل من هذه الفحوصات بشكل مستقل وفقًا للمتطلبات أو في عملية ضبط دقيق أو إصلاح قرارات خاطئة:
مقتطف من example-config.yaml:```yaml
policy:
allow_proxy_pass: True
allow_dynamic_peer_whitelisting: True
drop_invalid_useragent: True
drop_http_banned_header_names: True
drop_http_banned_header_value: True
drop_dangerous_ip_reverse_lookup: True
drop_ipgeo_metadata_containing_banned_keywords: True
drop_malleable_without_expected_header: True
drop_malleable_without_expected_header_value: True
drop_malleable_without_expected_request_section: True
drop_malleable_without_request_section_in_uri: True
drop_malleable_without_prepend_pattern: True
drop_malleable_without_apppend_pattern: True
drop_malleable_unknown_uris: True
drop_malleable_with_invalid_uri_append: True
By default all of these checks are enforced.
سيؤدي تشغيل `debug: True` إلى إغراق مخزن وحدة التحكم الخاص بك بالكثير من سطور السجل التي تصف كل خطوة يتخذها RedWarden في عملية اتخاذ القرار المعقدة.
إذا كنت تريد رؤية النصوص الكاملة لطلباتك واستجاباتك - فاضبط `debug` و `trace` على true وستغرق في عبء التسجيل!
## الأسئلة الشائعة
**- هل يمكن لهذا البرنامج العمل بدون ملف تعريف Malleable؟**
نعم يمكن ذلك. ومع ذلك، سيتم إيقاف تشغيل منطق فحص الطلب، وباقي الوظائف يجب أن تعمل بشكل جيد: فرض الموقع الجغرافي للـ IP، منطق البحث العكسي، قائمة عناوين IP المحظورة، إلخ.
**- هل يمكن تكييف هذا البرنامج بسهولة مع أطر عمل C2 الأخرى أيضًا؟ مثل Mythic، Covenant، إلخ؟**
بسهولة لا. مع بعض الجهد - نعم. كما وصفت أدناه، الأداة مكتوبة بشكل سيء مما سيجعل تكييفها مع أطر C2 الأخرى أمرًا مؤلمًا. ومع ذلك، هذا ممكن تمامًا مع بعض الوقت والجهد.
**- حزم البيانات الخاصة بي يتم إسقاطها. لماذا؟**
حاول تمكين `debug: True` و `trace: True` لجمع أكبر عدد ممكن من السجلات. بعد ذلك ستحتاج إلى مراجعة السجلات وفحص ما يحدث. هل تبدو الحزم تمامًا كما توقعتها في ملف تعريف Malleable الخاص بك؟ أم ربما حدث تلاعب خفي عبر الشبكة يتسبب في قيام RedWarden بإسقاط الحزمة (وقد يتسبب أيضًا في قيام Teamserver بإسقاطها؟).
## المشكلات المعروفة
- قد _تضيف_ عبئًا بسيطًا على إنتاجية السكون التفاعلي
- منطق معالجة ProxyPass بعيد عن الكمال وهو _مليء جدًا_ بالأخطاء (ولله كم هو قبيح!).
- يمكن لأشكال غريبة من ملفات التكوين أن تعطل محلل RedWarden وتجعله يشكو. أسهل طريقة لتجاوز ذلك هي نسخ `example-config.yaml` والعمل عليه بدلاً من ذلك.
## يا إلهي لماذا هذه الشفرة قطعة مهندسة سيئة للغاية؟
الشفرة هي _فوضى عارمة_ - أعترف بذلك - وهناك سبب صادق لذلك أيضًا: تم تطوير المشروع بنسبة 90% خلال مهام الفريق الأحمر الفعلية. كما نعلم جميعًا، تستلزم هذه المهام الكثير من الأشياء التي يجب القيام بها، مما لا يترك وقتًا تقريبًا لتطوير أدوات معقدة بشكل مناسب. ناهيك عن أهمية هذا البرنامج في إعداد المشروع. بدأت الأداة في البداية كبرنامج نصي وكيل بسيط مكتوب بلغة Python2، ثم تطورت لتكون وكيلًا مع إضافات، وتلقت إضافة `malleable_redirector` - ومنذ ذلك الحين وأنا أحاول جاهدًا الحفاظ على التوافق العكسي لـ `proxy2` (مسكين أنا، كنت مثل Microsoft!) مع الإضافات الأخرى التي صنعتها له والالتزام بغرضه الأصلي.
لكن حان الوقت للتخلي عنه، وإعادة تسميته والبدء في إصلاح جميع روائح الشفرة السيئة التي تم تقديمها.
مع كل ما قيل، يرجى إظهار بعض التعاطف معي عند رفع المشكلات، وتقديم طلبات السحب، وحاول المساعدة بدلاً من الحكم! :-)
شكرًا!
## المهام
- البحث في إمكانية استخدام خلاصات الاستخبارات التهديدية لأغراض خبيثة - مثل اكتشاف بائعي الأمان استنادًا إلى عناوين IP
- إضافة دعم لقاعدة بيانات/واجهة برمجة تطبيقات MaxMind GeoIP
- تنفيذ دعم لتوقيعات JA3 في كل من الكشف والحظر والانتحال لتزييف إعدادات nginx/Apache2/المخصصة.
- إضافة منطق تتبع فريد للإشارات لتوفير مرونة رفض عمليات التهيئة والاتصال وفقًا لتقدير الوكيل نفسه
- تقديم قيد زمني عند تقديم إمكانيات إعادة التوجيه (_الوكيل فقط خلال ساعات العمل_)
- إضافة منطق مصادقة وتفويض الوكيل على CONNECT/relay.
- إضافة إعادة توجيه مستهدفة لمستخدمي الجوال
- إضافة خيارات تكوين لتحديد رؤوس HTTP مخصصة ليتم حقنها، أو تلك التي سيتم إزالتها
- إضافة خيارات تكوين لتتطلب وجود رؤوس HTTP محددة في الطلبات التي تمر معايير ProxyPass.
- واجهة تفاعلية تسمح بكتابة أحرف بسيطة تتحكم في درجة تفصيل تسجيل المخرجات، على غرار Nmap
- إعادة كتابة منطق محلل ملف تعريف Malleable إلى [pyMalleableC2](https://github.com/Porchetta-Industries/pyMalleableC2). عندما بدأت في برمجة منطق المحلل الخاص بي لأول مرة، لم تكن هناك مثل هذه الأدوات على Github.
- إعادة هيكلة قاعدة الشفرة بأكملها
---
### ☕ أظهر الدعم ☕
هذا والمشاريع الأخرى هي نتيجة ليالٍ بلا نوم و**الكثير من العمل الجاد**. إذا كنت تحب ما أفعله وتقدر أنني دائمًا أعيد إلى المجتمع، [فكر في شراء فنجان قهوة لي](https://github.com/sponsors/mgeeky) _(أو الأفضل بيرة)_ فقط لقول شكرًا! 💪
---
## المؤلف```
Mariusz Banach / mgeeky, '19-'21
<mb [at] binary-offensive.com>
(https://github.com/mgeeky)